微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

处理 WaitForSingleObject - 响应式 UI

如何解决处理 WaitForSingleObject - 响应式 UI

我使用以下代码来了解如何在进程处于活动状态时等待进程结束。
在我的代码中,就在记事本打开时,我看到了 MessageBox

如何等到记事本关闭,而不会使我的表单无响应?

Public Class Form1
    Private Const WAIT_INFINITE = -1&
    Private Const SYNCHRONIZE = &H100000

    Private Declare Function OpenProcess Lib "kernel32" _
  (ByVal dwDesiredAccess As Long,ByVal bInheritHandle As Long,ByVal dwProcessId As Long) As Long

    Private Declare Function WaitForSingleObject Lib "kernel32" _
  (ByVal hHandle As Long,ByVal dwMilliseconds As Long) As Long

    Private Declare Function CloseHandle Lib "kernel32" _
  (ByVal hObject As Long) As Long

    Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        Dim hProcess As Long
        Dim taskId As Long
        Dim cmdline As String

        cmdline = "notepad.exe"
        taskId = Shell(cmdline,vbnormalFocus)

        hProcess = OpenProcess(SYNCHRONIZE,True,taskId)
        Call WaitForSingleObject(hProcess,WAIT_INFINITE)
        CloseHandle(hProcess)

        MsgBox ("The shelled app has ended.")
    End Sub
End Class

解决方法

在 .Net Framework / .Net Core 中,您可以使用异步、事件驱动的 WaitForExit 版本订阅 Exited 事件,该事件在您启动的进程终止时引发。

注意:该事件在 ThreadPool 线程中引发。您可以将 Process.SynchronizingObject 设置为当前 Form 实例以将事件编组到 UI 线程。

在 .Net Framework 中,将 [Process].StartInfo.UseShellExecute 设置为 False,因为默认值为 True
在 .Net Core 中,默认值已经是 False

当事件引发时,进程已经退出(HasExitedTrue),因此并非所有常用信息都可用。 Process.StartInfoProcessStartInfo 对象)是可访问的,当然还有 ExitTime 和其他值(在引发事件时检查 Process 对象)。

Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
    Dim p = New Process()
    p.StartInfo.FileName = "notepad.exe"
    p.StartInfo.UseShellExecute = False
    p.SynchronizingObject = Me
    p.EnableRaisingEvents = True
    AddHandler p.Exited,Sub()
            Dim processName = p.StartInfo.FileName
            Dim exitTime = p.ExitTime
            p?.Dispose()
            MessageBox.Show("Process exited")
            DoSomethingElseRelated(processName,exitTime)
        End Sub
    p.Start()
End Sub
,

最简单的,WaitForExitAsync 看起来像:

Private Async Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
    Dim p = Process.Start("notepad.exe")
    Await p.WaitForExitAsync()
    MsgBox ("The shelled app has ended.")
End Sub

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。