我正在编写一个程序,它允许我运行多个不同的硬件测试例程。为什么我的代理从backgroundworker调用在主线程中运行
这些例程可能相当耗时,持续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
是什么让你说DoWork事件正在UI线程中运行? – furkle 2014-10-30 16:51:11
如果'getMeasurement()'在一个线程中运行,那么这行:'Me.TextBox2.Text =(System.DateTime.Now - startTime).TotalSeconds.ToString'应该失败,因为您试图更新UI中的一个不是UI线程的线程。你有没有'CheckForIllegalCrossThreadCalls'被禁用了吗? – 2014-10-30 17:02:25
这完全正常,您使用表单的BeginInvoke()方法运行getMeasurement()。 *是必需的*,您不能从工作线程更新UI。 System.Timers.Timer没有任何用处,你可以使用winforms定时器。对于BackgroundWorker来说,它几乎是一样的,除了睡觉之外什么都不做。 – 2014-10-30 17:16:34