Ungültiger threadübergreifender Vorgang - wie oft habe ich mich schon über diese Fehlermeldung geärgert. Wenn ich in einem neuen Thread Eigenschaften von Controls auf einer Windowsforms setzen möchte, darf ich das nicht, da der Erstellerthread und der Thread, aus dem die Eigenschaft gesetzt werden soll, nicht identisch sind.
Bislang behalf ich mir mit folgendem mühevollen Workaround (anbei ein einfaches Beispiel zur Illustration in dem eine Progressbar in einem neuen Thread befüllt wird, um das Formular nicht zu blockieren):
Private
Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim th
As New Threading.Thread(
AddressOf FillProgressbar)
th.Start()
End Sub
Sub FillProgressbar()
For i As Integer = 1 To 100
SetzeWert(i)
System.Threading.Thread.Sleep(50)
Next
End Sub
Delegate Sub SetzeWerthandler(ByVal i As Integer)
Sub SetzeWert(ByVal i As Integer)
If Me.InvokeRequired Then
Dim caller As New SetzeWerthandler(AddressOf SetzeWert)
Me.Invoke(caller, i)
Else
Me.ProgressBar1.Value = i
End If
End Sub
Über einen neuen Thread wird die Methode FillProgressBar gestartet, der Sleep wurde eingebaut, damit das auch ein bisschen dauert.
Innerhalb dieser Routine kann ich jetzt den Wert nicht setzen, da ich sonst wieder meine geliebte Exception bekomme. Also rufe ich eine weitere Prozedur SetzeWert auf und übergebe den zu setzenden Wert.
Innerhalb von SetzeWert überprüfe ich die Eigenschaft InvokeRequired des Formulars. Falls diese Eigenschaft true ist, dann kann ich den Wert nicht direkt sitzen sondern muss einen passenden Delegate erstellen, der diese Methode über die Invoke-Methode des Formulars nochmal aufruft. Jetzt ist alles gut und der Wert kann problemlos gesetzt werden.
Das ganze war zwar etwas mühevoll, aber es lief zumindest und man gewöhnt sich ja irgendwann an alles.
Doch jetzt wird es peinlich. Aus zufall stolperte ich vor kurzem über die Eigenschaft CheckForIllegalCrossThreadCalls eines Windows Forms. Nun ja was soll ich sagen, einfach diese Eigenschaft auf true setzen und der ganze Spuk hat eine Ende.
Private
Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
System.Windows.Forms.Form.CheckForIllegalCrossThreadCalls = False
Dim th
As New Threading.Thread(
AddressOf FillProgressbar)
th.Start()
End Sub
Sub FillProgressbar()
For i As Integer = 1 To 100
ProgressBar1.Value = i
System.Threading.Thread.Sleep(50)
Next
End Sub
Naja vielleicht gibt es ja noch mehrere denen diese Eigenschaft nicht geläufig war.