Поиск…


Выполнение потокобезопасных вызовов с помощью Control.Invoke ()

Используя метод Control.Invoke() вы можете переместить выполнение метода или функции из фонового потока в поток, на который был создан элемент управления, который обычно является потоком пользовательского интерфейса (User Interface). Таким образом, ваш код будет помещен в очередь для запуска в потоке элемента управления, что устраняет возможность параллелизма.

Свойство Control.InvokeRequired также должно быть проверено, чтобы определить, нужно ли вам вызывать, или если код уже работает в том же потоке, что и элемент управления.

Метод Invoke() принимает делегат в качестве первого параметра. Делегат содержит ссылку, список параметров и тип возвращаемого значения для другого метода.

В Visual Basic 2010 (10.0) или выше лямбда-выражения могут использоваться для создания метода делегата «на лету»:

If LogTextBox.InvokeRequired = True Then
    LogTextBox.Invoke(Sub() LogTextBox.AppendText("Check passed"))
Else
    LogTextBox.AppendText("Check passed")
End If

Если в Visual Basic 2008 (9.0) или ниже, вы должны объявить делегата самостоятельно:

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

Выполнение потокобезопасных вызовов с использованием Async / Await

Если мы попытаемся изменить объект в потоке пользовательского интерфейса из другого потока, мы получим исключение операции поперечного потока:

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

Перед VB 14.0 и .NET 4.5 решение вызывало назначение и объект, живущий в потоке пользовательского интерфейса:

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

С VB 14.0 мы можем запустить Task в другом потоке, а затем восстановить контекст после завершения выполнения, а затем выполнить назначение с помощью Async / 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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow