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
相关产品推荐
相关产品推荐

