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
关键说明
- 事件处理程序必须改为
Async Sub:WPF允许事件处理方法使用Async Sub,这样才能通过Await等待异步方法完成,避免UI提前执行后续逻辑。 Task.Run传参方式:通过Function() Startit("参数")的Lambda表达式,即可合法传递参数,完全不需要依赖全局变量。- 原生异步进程等待:方案2中
WaitForExitAsync()是.NET 5+提供的原生异步API,比在后台线程中同步阻塞更高效,也更贴合异步编程模型。 - 关于
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
相关产品推荐
相关产品推荐

