使用事件从另一个类的BackgroundWorker更新UI(Using Events to upd

2019-10-22 12:39发布

我试图使用事件从一个不同的类更新从后台工作一个文本框。

这是中提到的相同问题这个SO后 ,除了我使用VB.NET。 我试图落实@ sa_ddam213 2号建议的解决方案。

我发现了一个错误:“跨线程操作无效:控制‘txtResult’从比它创建的线程以外的线程访问”

这里是我的代码:

Public Class DataProcessor
    Public Delegate Sub ProgressUpdate(ByVal value As String)
    Public Event OnProgressUpdate As ProgressUpdate

    Private Sub PushStatusToUser(ByVal status As String)
        RaiseEvent OnProgressUpdate(status)
    End Sub

    Public Sub ProcessAllFiles(ByVal userData As UserData)
        'Do the work
    End Sub
End Class

Public Class MainForm
    Private bw As New BackgroundWorker
    Private dp As New DataProcessor

    Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)

        If bw.CancellationPending = True Then
            e.Cancel = True
        Else
            dp.ProcessAllFiles(CType(e.Argument, UserData))
        End If
    End Sub

    Private Sub dp_OnProgressUpdate(ByVal status As String)
        txtResult.Text = status
    End Sub

    Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        bw.WorkerReportsProgress = True
        bw.WorkerSupportsCancellation = True
        AddHandler bw.DoWork, AddressOf bw_DoWork
        AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged
        AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted

        AddHandler dp.OnProgressUpdate, AddressOf dp_OnProgressUpdate
    End Sub
End Class

谢谢大家!

Answer 1:

该事件仍然来自不同的线程比UI。 您需要委托醒来回到UI。 我不检查InvokeRequired因为我知道它是从工作线程。

Me是形式, 调用请求将处理带来的数据到UI线程的工作委托。 在这里我代表Sub是一个lambda子,而不是使用正常的子程序-简单的设计。

Private Sub dp_OnProgressUpdate(ByVal status As String)
   'invoke the UI thread to access the control
   'this is a lambda sub
   Me.Invoke(Sub
               'safe to access the form or controls in here
               txtResult.Text = status
             End Sub)
 End Sub


Answer 2:

也许你可以尝试做这样的事情?

    Private Delegate Sub del_Update(ByVal status As String)

    Private Sub dp_OnProgressUpdate(ByVal status As String)
        If txtResult.InvokeRequired Then
            txtResult.Invoke(New del_Update(AddressOf dp_OnProgressUpdate),  New Object() {status})
        Else
            target_textbox.text = status 
        End If

    End Sub


文章来源: Using Events to update UI from a backgroundworker with another class