简体   繁体   English

处理 WaitForSingleObject - 响应式 UI

[英]Process WaitForSingleObject - responsive UI

I am using the following code for understanding how to wait for a Process to end while it's active.我正在使用以下代码来了解如何在进程处于活动状态时等待进程结束。
In my code, just when notepad opens, I see the MessageBox.在我的代码中,就在记事本打开时,我看到了 MessageBox。

How do I wait until Notepad is closed, without making my Form unresponsive?如何等到记事本关闭,而不让我的表单无响应?

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

In.Net Framework /.Net Core, you can use the asynchronous, event-driven, version of WaitForExit , subscribing to the Exited event, which is raised when the Process you started terminates.在 .Net Framework /.Net Core 中,您可以使用WaitForExit的异步事件驱动版本,订阅Exited事件,该事件在您启动的进程终止时引发。

Note : The event is raised in ThreadPool Threads.注意:该事件在 ThreadPool 线程中引发。 You can set the Process.SynchronizingObject to the current Form instance to marshal the events to the UI Thread.您可以将Process.SynchronizingObject设置为当前 Form 实例,以将事件编组到 UI 线程。

In.Net Framework, set [Process].StartInfo.UseShellExecute to False , since the default is True .在.Net Framework 中,将[Process].StartInfo.UseShellExecute设置为False ,因为默认值为True
In.Net Core the default is already False .在.Net Core 中,默认值已经是False

When the event is raised, the Process has already exited ( HasExited is True ), so not all the usual information is available.引发事件时,进程已经退出( HasExitedTrue ),因此并非所有常用信息都可用。 The Process.StartInfo (the ProcessStartInfo object) is accessible, plus of course the ExitTime and other values (inspect the Process object when the event is raised). Process.StartInfoProcessStartInfo对象)是可访问的,当然还有ExitTime和其他值(在引发事件时检查 Process object)。

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

At its simplest, a WaitForExitAsync would look like:最简单的 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM