我正在编写一个程序,允许我运行许多不同的硬件测试程序。
例程可能非常耗时,持续时间长达30分钟。在此期间,我必须控制一系列测试设备来设置条件并进行测量。
我当时认为使用后台工作人员执行任务将是理想的,并允许UI保持响应。这很有效,直到其中一个例程要求我每1.5秒进行一次测量。我正在使用系统计时器来触发这些事件。计时器是在后台工作程序的doWork子程序中创建和启动的,但是,我发现委托在主(UI)线程中运行,而不是像我想的那样在后台工作程序线程中运行。
我做错了吗?我附上了具有相同结构的简化程序的主要部分。
Private Sub getMeasurement()
' Runs in backgroundWorker thread
Me.TextBox2.Text = (System.DateTime.Now - startTime).TotalSeconds.ToString
startTime = System.DateTime.Now
Debug.Print("Thread name is " & Thread.CurrentThread.Name & ", ID = " & Thread.CurrentThread.ManagedThreadId)
End Sub
Private Sub OnTimedEvent()
'Runs in own thread, Calls getMeasurement which runs in BackgroundWorker thread
Thread.CurrentThread.Name = "OTE"
Debug.Print("In OnTimedEvent, thread = " & Thread.CurrentThread.Name & ", ID = " & Thread.CurrentThread.ManagedThreadId)
Dim ServiceTimerDelegate As New ServiceTimerDelegate(AddressOf getMeasurement)
Me.BeginInvoke(ServiceTimerDelegate)
End Sub
Private Sub backgroundWorker1_DoWork(ByVal sender As System.Object, _
ByVal e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Thread.CurrentThread.Name = "BW1"
mTimer = New Timers.Timer(1490) ' 14.9secs (allow for some latency)
AddHandler mTimer.Elapsed, New Timers.ElapsedEventHandler(AddressOf OnTimedEvent)
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
Dim i As Integer
'main timer for measurements every 1.5secs (may change to take interval from UI)
Select Case e.Argument
Case "Sunday"
mTimer.Start()
Debug.Print("Thread in DoWork = " & Thread.CurrentThread.Name & ", ID = " & Thread.CurrentThread.ManagedThreadId)
startTime = System.DateTime.Now
'main loop for temperature ramping
For i = 20 To 70
If (worker.CancellationPending = True) Then
e.Cancel = True
Else
Thread.Sleep(500)
worker.ReportProgress((i - 19) * (100 / 50))
i += 1
End If
Next
Case Else
e.Cancel = True
End Select
End Sub
答案 0 :(得分:0)
这里有三件事令人困惑,让我觉得你上面发布的代码并没有真正使用BackgroundWorker来实现它的功能。
DoWork事件始终在与UI不同的线程中运行。这就是它的全部要点。 ReportProgress在UI线程中运行,但您没有使用它。
在上面的代码中,您实际上似乎根本没有运行BackgroundWorker。相反,你似乎正在使用ServiceTimerDelegate - 不是100%确定我知道那是什么。您已经在DoWork处理程序中定义了BackgroundWorker(这没有任何意义),但您似乎从未将BackgroundWorker挂钩到该处理程序,也不会在其上调用RunWorkerAsync。
即使您在BackgroundWorker中运行getMeasurement(),它也会失败 - 您正在改变UI项目的内容,这会因InvalidCrossThreadAccess而导致异常。如果需要更改UI控件,请使用在UI线程中发生的ReportProgress事件。