You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET WinForm中Task.Run调用异步方法是否需使用Invoke

问题背景

使用第三方DLL提供的扫描相关事件时遇到问题,决定将扫描执行逻辑拆分到独立的DeskoScan子过程中,实现带延迟的异步调用,初始实现代码如下:

Public Async Sub DeskoScan()
  ListAdd("Perform scan START.")
  Try
    If _Duplex AndAlso _firstImageFileUploaded Then
      Await Task.Delay(1000) ' 等待确保前一次扫描相关的所有流程完全关闭
      Dim Aborted As Boolean
      Using frm = New countingForm
        frm.lblTime.Text = _My_Settings.Item("WaitForDialog").Value
        frm.lblMessage.Text = "请翻转文档扫描第二页" _
                  + vbCrLf + " - 准备好后按OK,或等待倒计时归零" _
                  + vbCrLf + " - 按Retry可额外等待" + _My_Settings.Item("WaitForDialog").Value + "秒" _
                  + vbCrLf + " - 按Abort直接取消操作"

        frm.btnRetry.DialogResult = DialogResult.None
        Aborted = frm.ShowDialog(Me) = DialogResult.Abort
      End Using

      If Aborted Then
        Exit Sub
      End If
    End If

    _deviceThread.Execute(Sub(ByVal device As Desko.Scan.Device)
                            device.Snapshot.Reset()
                            device.Snapshot.Infrared.Enabled = False
                            device.Snapshot.Infrared.Flags = Desko.Scan.ScanFlags.None
                            device.Snapshot.Infrared.ShutterWidthFactor = 1
                            device.Snapshot.Visible.Enabled = True
                            device.Snapshot.Visible.Flags = Desko.Scan.ScanFlags.DocumentClipping Or Desko.Scan.ScanFlags.AmbientFilter
                            device.Snapshot.Visible.ShutterWidthFactor = 1
                            device.Snapshot.Ultraviolet.Enabled = False
                            device.Snapshot.Ultraviolet.Flags = Desko.Scan.ScanFlags.None
                            device.Snapshot.Ultraviolet.ShutterWidthFactor = 1
                            device.Snapshot.Resolution = Desko.Scan.Resolution.Full
                            device.Snapshot.Perform()
                          End Sub)
  Catch ex As Exception
    ListAdd(ex.ToString())
  End Try
End Sub

由于该过程包含UI操作,需要在UI主线程执行,此前通过判断InvokeRequired属性做线程封送,代码如下:

If Me.InvokeRequired Then
  Me.Invoke(Sub() DeskoScan())
Else
  DeskoScan()
End If

现在需要在扫描完成事件HandleSnapshotCompleted中异步触发该逻辑,初步使用Task.Run实现调用,代码如下:

Private Sub HandleSnapshotCompleted(ByVal sender As Object, ByVal args As Desko.Scan.SnapshotCompletedEventArgs)
  If _Duplex AndAlso _firstImageFileUploaded Then
    Task.Run(Sub() DeskoScan()) ' 仅这样写是否足够?是否还需要搭配Me.Invoke做线程封送?
  Else
    ListAdd("扫描完成,可以取走文档。")
    Minimize()
  End If
End Sub

初始疑问:该场景下仅使用Task.Run调用是否足够,是否还需要额外搭配Me.Invoke做线程封送?因当前缺少配套扫描硬件,无法实际运行测试代码验证。

问题更新

经确认,该场景下不需要使用Task.Run,但需要将子过程声明为Async并搭配Await关键字,保证扫描对象的所有事件处理器都能正常执行完成,通过Await Task.Delay(2000)即可实现子过程的异步执行,更新后的代码框架如下:

Public Async Sub DeskoScan()
  If Me.InvokeRequired Then
    Me.Invoke(Sub() DeskoScan())
  Else
    Await Task.Delay(2000)
    ' 其余扫描逻辑
    ....
  End If
End Sub

内容的提问来源于stack exchange,提问作者Dejan Dozet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 13:24:26