Visual Basic .NET Language
threading
Ricerca…
Esecuzione di chiamate thread-safe tramite Control.Invoke ()
Utilizzando il metodo Control.Invoke()
è possibile spostare l'esecuzione di un metodo o una funzione da un thread in background al thread su cui è stato creato il controllo, che di solito è il thread dell'interfaccia utente (User Interface). In questo modo il codice verrà messo in coda per l'esecuzione sul thread del controllo, che rimuoverà la possibilità di concorrenza.
La proprietà Control.InvokeRequired
dovrebbe inoltre essere controllata per determinare se è necessario richiamare o se il codice è già in esecuzione sullo stesso thread del controllo.
Il metodo Invoke()
accetta un delegato come primo parametro. Un delegato mantiene il riferimento, l'elenco dei parametri e il tipo restituito con un altro metodo.
In Visual Basic 2010 (10.0) o versioni successive, è possibile utilizzare espressioni lambda per creare al volo un metodo delegato:
If LogTextBox.InvokeRequired = True Then
LogTextBox.Invoke(Sub() LogTextBox.AppendText("Check passed"))
Else
LogTextBox.AppendText("Check passed")
End If
Considerando che in Visual Basic 2008 (9.0) o inferiore, è necessario dichiarare il delegato per conto proprio:
Delegate Sub AddLogText(ByVal Text As String)
If LogTextBox.InvokeRequired = True Then
LogTextBox.Invoke(New AddLogText(AddressOf UpdateLog), "Check passed")
Else
UpdateLog("Check passed")
End If
Sub UpdateLog(ByVal Text As String)
LogTextBox.AppendText(Text)
End Sub
Esecuzione di chiamate thread-safe usando Async / Attesa
Se proviamo a cambiare un oggetto sul thread dell'interfaccia utente da un thread diverso, otterremo un'eccezione di operazione cross-thread:
Private Sub Button_Click(sender As Object, e As EventArgs) Handles MyButton.Click
' Cross thread-operation exception as the assignment is executed on a different thread
' from the UI one:
Task.Run(Sub() MyButton.Text = Thread.CurrentThread.ManagedThreadId)
End Sub
Prima di VB 14.0 e .NET 4.5 la soluzione stava invocando l'assegnazione on e object living sul thread dell'interfaccia utente:
Private Sub Button_Click(sender As Object, e As EventArgs) Handles MyButton.Click
' This will run the conde on the UI thread:
MyButton.Invoke(Sub() MyButton.Text = Thread.CurrentThread.ManagedThreadId)
End Sub
Con VB 14.0, possiamo eseguire Task
su un thread diverso e quindi sfruttare al contesto ripristinata quando l'esecuzione è completa e quindi eseguire l'assegnazione con asincrono / Await:
Private Async Sub Button_Click(sender As Object, e As EventArgs) Handles MyButton.Click
' This will run the code on a different thread then the context is restored
' so the assignment happens on the UI thread:
MyButton.Text = Await Task.Run(Function() Thread.CurrentThread.ManagedThreadId)
End Sub