Verwendet man in einer Form rechenintensive Vorgänge ohne diese in einem Thread auszulagern, dann reagiert die Form für die Zeit der Ausführung des Vorgangs nicht. Dies lässt den Nutzer glauben, das Programm hätte sich aufgehängt.
(Typisches Beispiel: Der WindowsEditor mit großen Dateien)
Es empfiehlt sich also diese Vorgänge in einen Thread auszulagern. Manchmal möchte man während des Vorgangs Informationen in der Form ausgeben. z.B. wenn man eine größere Datei verarbeitet eine ProgressBar aktualisieren.
Versucht man von einem anderen Thread auf die Steuerelemente des WindowThreads zuzugreifen, wird dieser Zugriff standartmäßig verweigert.
Diese Meldung lässt sich unterdrücken.
Dies ist aber in etwa so sinnvoll wie, wenn man öfter einen Autounfall hat und sich beschwert, dass man ständig den Airbag ins Gesicht bekommt. Und anstatt weniger Unfälle zu bauen, baut man lieber den Airbag aus.
[Quelle: Stackoverflow]
Die richtige Lösung ist Invoking. Man prüft vor dem Zugriff auf das Steuerelement, ob man einen thread-übergreifenden Vorgang durchführen würde (ein Invoke nötig ist).
Dazu erstellt man eine Methode, welche die gewünschte Funkion ausführt (Man bezeichnet solche Methoden auch als getter und setter-Methoden).
Die Funktion überprüft, ob ein Invoke nötig ist, und wenn ja fordert sie einen Invoke beim Steuerelement an und gibt sich selbst als Callback an. Das heist die Funktion ruft sich solange selbst auf, bis der Vorgang sicher durchführbar ist.
Da wir hier mit einem Callback arbeiten, brauchen wir auch noch ein delegate.
- private delegate void SetProgressBarValueCallback(int value);
- private void SetProgressBarValue(int value)
- {
- // Invoke nötig?
- if (progressBar1.InvokeRequired)
- {
- // Invoke nötig
- progressBar1.Invoke(new SetProgressBarValueCallback(value));
- }
- else
- {
- // Kein Invoke nötig - Vorgang sicher durchführbar
- progressBar1.Value = value;
- }
- }
Jetzt kann man in seinem eigenen Thread SetProgressBarValue(10) aufrufen und die ProgressBar verändert sich ohne Probleme.
Gruß
florian0