[C# 3.5] Threads und Rückmeldungen an GUI

meilon

Erfahrenes Mitglied
Hallo!

Ich habe mir ein kleines Helferlein gebaut welches auch schon wie gedacht funktioniert. Da das Programm Netzwerkverbindungen aufbaut und diese ja nicht vorhersehbar sind möchte ich eine kleine Animation darstellen, dass der User sich doch bitte gedulden solle (oder sowas in der Art).

Momentan startet das Programm, baut die Verbindung auf und solange keine Antwort oder Timout erfolgt, hängt das Programm. Sehr unschön!

Über Threads müsste das doch eigentlich zu lösen sein oder? Ich habe mir auch schon einige Sachen dazu angeschaut und auch ein wenig rumprobiert, aber was mir fehlt ist ein Event, wenn der Thread fertig ist.
Theoretisch könnte ich mit einem Timer eine Variable der ausführenden Klasse überwachen, aber das ist ja auch nicht auf dem Stand der Technik.

Wo finde ich etwas zu Threads in GUI Anwendungen? Mit Codebeispielen und ein wenig Infos zum Thema. Es würde mich auch ein Codehappen reichen, mit dem ich die eigentlich gar nicht so schlechte Hilfe von Visual Studio Express füttern könnte.

Beste Grüße
meilon
 

MCoder

Erfahrenes Mitglied
Hallo meilon,

speziell für Interaktionen mit der GUI (Fortschritt-, Ende-Event) solltest du dir mal die BackgroundWorker-Klasse anschauen.

Gruß
MCoder
 

Nico Graichen

Erfahrenes Mitglied
Dazu kannst du dir auch noch die Invoke-Methode der Control-Klasse anschauen. Wenn du zum Beispiel Timer (System.Threading) oder FileSystemWatcher-Objekte nutzt, benötigst du diese auf jeden Fall, um Daten an den GUI-Thread weiterzureichen
 

meilon

Erfahrenes Mitglied
Danke für den Tipp mit dem Background Worker - war ja wieder mal viel zu einfach :D Reinziehen, umbenennen und auf die Events Doppelklicken. Noch ein Result hergeben und Fertig.

Invoke wäre wohl eine Alternative gewesen, aber so gefällt es mir doch besser: Keep it Simple!

Beste Grüße
meilon
 

meilon

Erfahrenes Mitglied
Hmm, leider doch nicht ganz so erfolgreich wie gedacht:

Ich habe jetzt insgesammt 3 Background Worker wovon 2 quasi voneinander Abhängen:

1. Aktualisierung der Informationen
2. Prüfen ob Update vorhanden ist
3. Update downloaden.

Bei den letzten beiden werden Message Boxen angezeigt, wenn es was neues zu berichten gibt. Ist eine davon offen während im Hintergrund eigentlich der erste Background-Worker startet, kommt es ab und zu Exceptions.

Da ich das Problem jetzt leider nicht reproduzieren kann, hier eine ungefähre Beschreibung:
Fehler tritt auf in Program.cs (der automatisch generierten) in der Main-Methode unter dem Aufruf "Application.Run(new frmMain());".
Meldung bekomme ich jetzt nicht mehr zusammengestammelt (schlecht, ich weiß), liefere ich aber nach, wenn sie mal wieder auftritt.

Ideen schon mal vorab?
 

MCoder

Erfahrenes Mitglied
Wo öffnest du die Message-Boxen, innerhalb des BackgroundWorkers (DoWork) oder als Reaktion auf ein Event des BackgroundWorkers?

Gruß
MCoder
 

meilon

Erfahrenes Mitglied
Die Messageboxen werden immer in RunWorkerCompleted eröffnet. Da das ja nun wieder GUI-Thread ist kann ich mir schon vorstellen das bei einem Modalen Fenster im Hintergrund was schief gehen kann, was ich aber nicht kapiere: Warum tritt das nur ab und zu auf? Zuletzt konnte ich das ja gar nicht mehr gewollt hervorrufen.

Ich melde mich, wenn ich die Fehlermeldung irgendwann doch noch mal sehe!
 

meilon

Erfahrenes Mitglied
Soo, habs geschafft. War natürlich gerade nicht gewollt, das die Meldung kommt, aber nun, hier ist sie:

TargetInvocationException wurde nicht behandelt.
Ein Aufrufziel hat einen Ausnahmefehler verursacht

Im Ausgabefenster sind diese zwei Zeilen zu lesen:
Eine Ausnahme (erste Chance) des Typs "System.InvalidOperationException" ist in System.dll aufgetreten.
Eine Ausnahme (erste Chance) des Typs "System.Reflection.TargetInvocationException" ist in mscorlib.dll aufgetreten.

Jetzt habe ich mir die InnerException dazu angeschaut und konnte folgende Meldung entlocken:
Dieser BackgroundWorker ist derzeit ausgelastet und kann nicht mehrere Aufgaben gleichzeitig ausführen.

Der Trace dazu:
Code:
   bei System.ComponentModel.BackgroundWorker.RunWorkerAsync(Object argument)
   bei System.ComponentModel.BackgroundWorker.RunWorkerAsync()
   bei AMTStatus.frmMain.timerCheckState_Tick(Object sender, EventArgs e) in H:\\Visual Studio 2008\\Projects\\AMTStatus\\AMTStatus\\frmMain.cs:Zeile 200.
   bei System.Windows.Forms.Timer.OnTick(EventArgs e)
   bei System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
   bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   bei System.Windows.Forms.SafeNativeMethods.MessageBox(HandleRef hWnd, String text, String caption, Int32 type)
   bei System.Windows.Forms.MessageBox.ShowCore(IWin32Window owner, String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, MessageBoxOptions options, Boolean showHelp)
   bei System.Windows.Forms.MessageBox.Show(String text, String caption, MessageBoxButtons buttons, MessageBoxIcon icon)
   bei AMTStatus.frmMain.bwDownloadUpdate_RunWorkerCompleted(Object sender, RunWorkerCompletedEventArgs e) in H:\\Visual Studio 2008\\Projects\\AMTStatus\\AMTStatus\\frmMain.cs:Zeile 440.
   bei System.ComponentModel.BackgroundWorker.OnRunWorkerCompleted(RunWorkerCompletedEventArgs e)
   bei System.ComponentModel.BackgroundWorker.AsyncOperationCompleted(Object arg)

Der timerCheckState_Tick macht alle 5 Sekunden die Abfrage. Kann also in diesem Fall gewesen sein, dass der Rechner noch nicht innerhalb der 5 Sekunden geantwortet hat und der BW eben noch beschäftigt ist. Zufällig war dann jetzt auch noch eine Messagebox von einem anderen BW_RunWorkerCompleted offen.

Habe jetzt vor dem RunWorkerAsync ein If-Abfrage auf IsBusy drin.

Das sollte die Sache behoben haben - hoffentlich....
 

Neue Beiträge