Moin Leute,
die Verwendung von
Das Beispiel arbeitet ohne Threads, dafür ist es sehr einfach gehalten und ohne Kommentare verständlich.
Ablauf: An eine String-List werden Zahlen (.ToString) angehängt, die Reihenfolge der Aufrufe und die Reihenfolge der List-Elemente Ziel der Untersuchung.
Kern sind 2 Routinen, die äußerlich (fast) gleich aussehen, sie unterscheiden sich lediglich in der verwendeten
Getestet wird mit 3 Button-Click-Routinen, die je eine der Testroutinen aufrufen. Bei der dritten Button-Routine hab ich noch ein
Der Ablauf ist gleich, die Liste wird gelöscht, es werden die Testroutinen aufgerufen und es wird die aufgebaute Liste ausgegeben.
GUI: Form mit 3 Button und einer RichTextBox, alles mit Default-Properties:
Spoiler anzeigen
Dies ist der Output:
Bei der Verwendung von
Bei der Verwendung von
Bei der Verwendung von
Was passiert?
Diese Werte sind allerdings vorhanden, überzeugt Euch mit folgender Erweiterung davon:
Überprüft genau, welchen Code Ihr bei
die Verwendung von
BeginInvoke()
an Stelle von Invoke()
kann zu unerwarteten Ergebnissen führen, ich möchte Euch an meinen Untersuchungen teilhaben lassen.Das Beispiel arbeitet ohne Threads, dafür ist es sehr einfach gehalten und ohne Kommentare verständlich.
Ablauf: An eine String-List werden Zahlen (.ToString) angehängt, die Reihenfolge der Aufrufe und die Reihenfolge der List-Elemente Ziel der Untersuchung.
Kern sind 2 Routinen, die äußerlich (fast) gleich aussehen, sie unterscheiden sich lediglich in der verwendeten
Invoke
-Prozedur, einmal Invoke()
, einmal BeginInvoke()
.Getestet wird mit 3 Button-Click-Routinen, die je eine der Testroutinen aufrufen. Bei der dritten Button-Routine hab ich noch ein
Application.DoEvents()
reingeschrieben, dieser dritte Test kam als Folge der Ergebnisse der zweiten Button-Click-Routine hinzu. Der Ablauf ist gleich, die Liste wird gelöscht, es werden die Testroutinen aufgerufen und es wird die aufgebaute Liste ausgegeben.
GUI: Form mit 3 Button und einer RichTextBox, alles mit Default-Properties:
VB.NET-Quellcode
- Public Class Form1
- Private MyList As New List(Of String)
- Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
- Me.MyList.Clear()
- Me.MyList.Add("Invoke:")
- Me.Test1()
- Me.RichTextBox1.Lines = Me.MyList.ToArray()
- End Sub
- Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
- Me.MyList.Clear()
- Me.MyList.Add("BeginInvoke:")
- Me.Test2()
- Me.RichTextBox1.Lines = Me.MyList.ToArray()
- End Sub
- Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
- Me.MyList.Clear()
- Me.MyList.Add("BeginInvoke + DoEvents:")
- Me.Test2()
- Application.DoEvents()
- Me.RichTextBox1.Lines = Me.MyList.ToArray()
- End Sub
- Private Sub Test1()
- Me.AddNumber(1)
- Me.Invoke(Sub() AddNumber(2))
- Me.AddNumber(3)
- Me.Invoke(Sub() AddNumber(4))
- Me.AddNumber(5)
- Me.Invoke(Sub() AddNumber(6))
- Me.AddNumber(7)
- End Sub
- Private Sub Test2()
- Me.AddNumber(1)
- Me.BeginInvoke(Sub() AddNumber(2))
- Me.AddNumber(3)
- Me.BeginInvoke(Sub() AddNumber(4))
- Me.AddNumber(5)
- Me.BeginInvoke(Sub() AddNumber(6))
- Me.AddNumber(7)
- End Sub
- Private Sub AddNumber(number As Integer)
- Me.MyList.Add(number.ToString())
- End Sub
- End Class
Bei der Verwendung von
Invoke()
stimmt die Ausgabereihenfolge mit der Aufrufreihenfolge überein.Bei der Verwendung von
BeginInvoke()
stimmt die Ausgabereihenfolge nicht mit der Aufrufreihenfolge überein, die Elemente, die mit BeginInvoke() hinzugefügt werden, werden nicht angezeigt.Bei der Verwendung von
BeginInvoke()
stimmt die Ausgabereihenfolge nicht mit der Aufrufreihenfolge überein, die Elemente, die mit BeginInvoke() hinzugefügt werden, werden angezeigt.Was passiert?
Invoke()
lässt den Invoke-Code im GUI-Thread ausführen, wenn er aufgerufen wird.BeginInvoke()
lässt den Invoke-Code im GUI-Thread ausführen, bevor die GUI in den Idle-Zustand zurückkehrt. Da dies im Beispiel erst nach dem Anzeigen der List in der RichTextBox der Fall, die mit BeginInvoke()
angehängten Werte werden nicht angezeigt.Diese Werte sind allerdings vorhanden, überzeugt Euch mit folgender Erweiterung davon:
BeginInvoke() und DoEvents()
lässt den Invoke-Code im GUI-Thread ausführen, wenn DoEvents()
aufgerufen wird, deswegen ist die Aufruf-Reihenfolge verschieden von der Anzeigereihenfolge.Überprüft genau, welchen Code Ihr bei
Invoke()
und BeginInvoke()
aufruft, denn das Resultat kann anders ausfallen, als Ihr es erwartet. Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert!
Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch
Ein guter .NET-Snippetkonverter (der ist verfügbar).
Programmierfragen über PN / Konversation werden ignoriert!