Hallo,
ich habe ein Projekt, welches über eine GUI mehrere Prozesse(zwischen einem und acht) startet.
Diese Prozesse überprüfen extern eine Hardware, indem sie Daten rausschicken und wieder empfangen. Die empfangenen Daten werden dann in je eine RichTextBox über einen asynchronen DataReceiveEvent und einen Delegaten geschrieben.
Bis dahin funktioniert alles wie gewollt.
Problematisch wird dann das Stoppen des Lese-Schreibe Testvorgangs bzw. dieser Prozesse.
Die GUI ist nicht eingefroren(d.h. Textbox wird ständig aktualisiert und wenn man mit der Maus über einen Button fährt, wird dieser auch hellblau unterlegt), aber der StopButton-Clickevent wird beim Clicken trotzdem nicht aufgerufen.
Ich vermute, dass die GUI mit dem Füllen der Textboxen einfach zu beschäftigt ist, um den ButtonClickEvent einzuleiten.
Gibt es hierfür einen Lösungsvorschlag?
Da ich noch ein Anfänger bin, freue ich mich über jeden Tipp und Verbesserungsvorschlag!
LG Manuel
Edit:
private void btnProcessStart_Click(object sender, EventArgs e)
{
Thread ThreadModul1 = new Thread(new ParameterizedThreadStart(Modul1));
if(!ThreadModul1.IsAlive)ThreadModul1.Start(ProzessFile);
}
public void Modul1(object ProzessFilename)
{
PModul1.StartInfo.FileName = ProzessFilename.ToString();
PModul1.StartInfo.UseShellExecute = false;
PModul1.StartInfo.RedirectStandardOutput = true;
PModul1.StartInfo.RedirectStandardInput = true;
PModul1.StartInfo.RedirectStandardError = true;
PModul1.StartInfo.CreateNoWindow = true;
PModul1.Start();
PModul1.OutputDataReceived += new DataReceivedEventHandler((s, e) => { SetText("\r\n" + e.Data, 1); });
PModul1.ErrorDataReceived += new DataReceivedEventHandler((s, e) => { SetText("\r\n" + e.Data, 1); });
PModul1.BeginOutputReadLine();
PModul1.BeginErrorReadLine();
}
private void SetText(string TextLine, Int16 ID)
{
if(ID == 1)
{
AddTextDelegate del = new AddTextDelegate(AddText);
Invoke(del, ListModul1, TextLine, Color.Black);
}
if(ID == 2)
{
//usw }
}
delegate void AddTextDelegate(RichTextBox rtb, string txt, Color col);
private void AddText(RichTextBox rtb, string txt, Color col)
{
try
{
int pos = rtb.TextLength;
rtb.AppendText(txt);
rtb.Select(pos, txt.Length);
rtb.Select();
rtb.SelectionColor = col;
rtb.SelectionStart = rtb.Text.Length;
rtb.ScrollToCaret();
}
catch { }//MessageBox.Show("Error at AddText to List"); }
}
Hallo ManuelB,
mehr als den Text aus deiner Frage wissen wir nicht, daher kann auch keine genaue Antwort gegeben werden. Aber schau dir [Artikel] Debugger: Wie verwende ich den von Visual Studio? an, damit kannst du vllt. die Ursache lokalisieren.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Sieht für mich so aus das da zwar mit Threads gearbeitet wird, aber dann doch alles in den Gui Thread delegiert wird.
Siehe "Achtung: GUI-Zugriffe nur aus dem GUI-Thread" und "Achtung: Die Falle" in
[FAQ] Warum blockiert mein GUI?
Hallo,
danke für die schnellen Antworten.
Ich werde mir die von euch verlinkten Artikel gleich mal durchlesen.
Vielen Dank im Voraus
Manuel
Wenn du nur einen Thread hast, solltest du ggf. direkt auf den BackgroundWorker umstellen.
Ansonsten scheint deine GUI zu blockieren, was meistens daran liegt das du deine Verarbeitungen nicht im Kontext des ausgelagerten sondern im GUI Thread machst.
Eine Umstellung auf den BackgroundWorker scheint auf den ersten Blick sinnvoller zu sein.
Du musst dann eben nur Invoke aufrufen, wenn du die Controls der GUI aufrufen willst.
Aber dazu gibt es genug Anleitungen im Forum und Googel + den geposteten Artikel zu dem Thema blockierende GUI.
Nachtrag:
@ManuelB
Es wäre hilfreicher, wenn du nicht den gesamten Code doppelt postet.
Editiere dafür bitte deinen ersten Post ganz oben.
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
++:::
Ansonsten können manche Antworten nicht mehr nachvollzogen werden!! Dann lieber verändert doppelt posten (den relevanten Teil).
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Ich würde an Deiner Stelle Deine Updates nur alle x ms im Block verarbeiten.
Eine Möglichkeit wäre es, eine Blocking Collection zu benutzen.
DataReceived schreibt in die Blocking Collection und ein eigener Update-Thread fast alle Änderungen in einem Schritt zusammen und ruft dann einmal für x ms das Invoke auf.
Und genau das ist zB in TPL Pipelines sehr gut beschrieben.
Sowas ist auch viel leichter umzusetzen, zu warten und zu skalieren.
Man sollte auch eher Tasks nutzen - sofern möglich - da sie sowohl für die Anwendung wie auch drum herum einfacher zu handlen und zu skalieren sind als Threads.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Vielen Dank an alle!
Eure Tipps haben mir wirklich sehr geholfen.
Ich habe mich nun für eine geblockte Ausgabe alle x ms entschieden und es klappt!!
LG Manuel