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

VB实现C#的Await Await等效操作,解决WPF UI线程阻塞问题

解决方案

问题核心

你的代码存在两个关键问题:

  • Button_Click调用StartitAsync时未使用Await,导致后续代码会立即执行
  • 使用TaskFactory.StartNew时未正确处理嵌套任务,且对Task.Run传参的用法有误

修正后的代码(两种方案)

方案1:保留原有同步Startit方法,用Task.Run正确传参

Class MainWindow
    ' WPF事件处理程序需改为Async Sub才能使用Await
    Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)
        Await StartitAsync()
        MsgBox("Returned from StartitAsync")
    End Sub

    Private Async Function StartitAsync() As Task(Of Integer)
        ' 通过Lambda表达式给Task.Run传递参数,无需全局变量
        Dim Rc As Integer = Await Task.Run(Function() Startit("notepad.exe"))
        MsgBox("Returned from await of Startit, RC is " & Rc)
        Return Rc
    End Function

    Private Function Startit(Pgm As String) As Integer
        Dim RC As Integer = 8 ' 默认返回失败码
        Dim Startinfo As New ProcessStartInfo With {
            .WindowStyle = ProcessWindowStyle.Maximized,
            .FileName = Pgm,
            .Arguments = ""
        }

        Using PgmProcess As Process = Process.Start(startInfo:=Startinfo)
            PgmProcess.WaitForExit()
            If PgmProcess.HasExited Then
                RC = PgmProcess.ExitCode
            End If
        End Using
        Return RC
    End Function
End Class

方案2:将Startit改为异步方法(推荐,符合.NET异步规范)

直接使用Process.WaitForExitAsync()替代同步阻塞的WaitForExit(),避免占用后台线程:

Class MainWindow
    Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)
        Await StartitAsync()
        MsgBox("Returned from StartitAsync")
    End Sub

    Private Async Function StartitAsync() As Task(Of Integer)
        Dim Rc As Integer = Await Startit("notepad.exe")
        MsgBox("Returned from await of Startit, RC is " & Rc)
        Return Rc
    End Function

    Private Async Function Startit(Pgm As String) As Task(Of Integer)
        Dim RC As Integer = 8
        Dim Startinfo As New ProcessStartInfo With {
            .WindowStyle = ProcessWindowStyle.Maximized,
            .FileName = Pgm,
            .Arguments = ""
        }

        Using PgmProcess As Process = Process.Start(startInfo:=Startinfo)
            ' 异步等待进程退出,无线程阻塞
            Await PgmProcess.WaitForExitAsync()
            If PgmProcess.HasExited Then
                RC = PgmProcess.ExitCode
            End If
        End Using
        Return RC
    End Function
End Class

关键说明

  1. 事件处理程序必须改为Async Sub:WPF允许事件处理方法使用Async Sub,这样才能通过Await等待异步方法完成,避免UI提前执行后续逻辑。
  2. Task.Run传参方式:通过Function() Startit("参数")的Lambda表达式,即可合法传递参数,完全不需要依赖全局变量。
  3. 原生异步进程等待:方案2中WaitForExitAsync()是.NET 5+提供的原生异步API,比在后台线程中同步阻塞更高效,也更贴合异步编程模型。
  4. 关于TaskFactory.StartNew的嵌套任务问题:如果一定要用该方法,需要通过Await Await或Unwrap()等待内部任务完成,示例代码如下,但这种写法不如Task.Run简洁,不推荐使用:
    Dim tf As New TaskFactory
    Dim outerTask As Task(Of Task(Of Integer)) = tf.StartNew(AddressOf Startit, "notepad.exe")
    Dim Rc As Integer = Await Await outerTask
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:01:58