写给 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
你好,我有一个小型应用程序
问题是当我在主线程上 运行 任务时,程序 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