0

我正在编写一个程序,它允许我运行许多不同的硬件测试例程。

这些例程可能非常耗时,持续长达 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
4

1 回答 1

0

这里有三件事令人困惑,让我认为您在上面发布的代码实际上并未使用 BackgroundWorker 的功能。

  1. DoWork 事件始终在与 UI 不同的线程中运行。这就是它的全部意义所在。ReportProgress 在 UI 线程中运行,但您没有使用它。

  2. 在上面的代码中,您实际上根本没有运行 BackgroundWorker。相反,您似乎正在使用 ServiceTimerDelegate - 不是 100% 确定我知道那是什么。您已经在 DoWork 处理程序中定义了一个 BackgroundWorker(这没有意义),但您似乎从未真正将 BackgroundWorker 连接到该处理程序,也没有在其上调用 RunWorkerAsync。

  3. 即使您在 BackgroundWorker 中运行 getMeasurement(),它也应该会失败 - 您正在更改 UI 项的内容,这会由于 InvalidCrossThreadAccess 而导致异常。如果您需要更改 UI 控件,请使用在 UI 线程中发生的 ReportProgress 事件。

于 2014-10-30T16:55:02.130 回答