写给 textbox.text 而 运行 backgroundworker VB.net

Write to textbox.text while running backgroundworker VB.net

你好,我有一个小型应用程序

问题是当我在主线程上 运行 任务时,程序 window 没有响应

所以我的按钮将任务重定向到 backgroudworker:

Private Sub btn_start_Click(sender As Object, e As EventArgs) Handles btn_start.Click

    BackgroundWorker1.RunWorkerAsync()

End Sub

现在我想在一个 Sub 中多次从这个 Backgroudworker 输出一些文本到我的文本框 (txtlog)。我找到了一个允许这样做的解决方案。但是如果我不得不多次使用它,这会使代码变得非常丑陋:

例子

Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

        If txtLog.InvokeRequired Then
            txtLog.Invoke(Sub() txtLog.AppendText("My text" & vbNewLine))
            txtLog.Invoke(Sub() txtLog.ScrollToCaret())
        Else
            txtLog.AppendText("My text" & vbNewLine)
            txtLog.ScrollToCaret()
        End If

        Something in Backgroudworker . . .


        If txtLog.InvokeRequired Then
            txtLog.Invoke(Sub() txtLog.AppendText("My text" & vbNewLine))
            txtLog.Invoke(Sub() txtLog.ScrollToCaret())
        Else
            txtLog.AppendText("My text" & vbNewLine)
            txtLog.ScrollToCaret()
        End If
        

       . . . 

End Sub

有没有更短的方法可以让我在文本框中书写?

使用 BackgroundWorker 的全部意义在于您不必调用 Invoke 和使用委托。如果您无论如何都要这样做,那么 BackgroundWorker 毫无意义。

关于您的代码,当您知道 DoWork 事件处理程序将在后台线程上执行时,测试 InvokeRequired 的意义何在?它总是 True。另外,为什么你要调用 Invoke 两次并添加所有开销,而你可以调用它一次并在一次调用中做你想做的很多事情?

Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    txtLog.Invoke(Sub()
                      txtLog.AppendText("My text" & vbNewLine))
                      txtLog.ScrollToCaret()
                  End Sub)

正如我所说,您根本不应该调用 Invoke。如果您想在 BackgroundWorker 的 UI 线程上执行某些操作,那么您可以调用 ReportProgress 并处理 ProgressChanged 事件。您要执行的代码进入事件处理程序,您可以根据需要调用 ReportProgress。如果您需要传递数据,您可以使用 ReportProgress 的第二个参数并在事件处理程序中从 e.UserState 取回它。这是我之前准备的:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    'Raise the DoWork event in a worker thread.
    Me.BackgroundWorker1.RunWorkerAsync()
End Sub
 
'This method is executed in a worker thread.
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, _
                                     ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    Dim worker As System.ComponentModel.BackgroundWorker = DirectCast(sender, System.ComponentModel.BackgroundWorker)
 
    For i As Integer = 1 To 100
        'Raise the ProgressChanged event in the UI thread.
        worker.ReportProgress(i, i & " iterations complete")
 
        'Perform some time-consuming operation here.
        Threading.Thread.Sleep(250)
    Next i
End Sub
 
'This method is executed in the UI thread.
Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, _
                                              ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    Me.ProgressBar1.Value = e.ProgressPercentage
    Me.Label1.Text = TryCast(e.UserState, String)
End Sub
 
'This method is executed in the UI thread.
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, _
                                                 ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
    Me.Label1.Text = "Operation complete"
End Sub