异步进程开始并等待其完成

25 浏览
0 Comments

异步进程开始并等待其完成

我对.NET中的线程模型还不熟悉。你会用什么来:

  1. 启动处理文件的进程 (process.StartInfo.FileName = fileName;)
  2. 等待用户关闭进程或在一段时间后放弃线程。
  3. 如果用户关闭了进程,删除该文件。

启动进程和等待应该在与主线程不同的线程上进行,因为这个操作不应影响应用程序。

例如:

我的应用程序生成一个HTML报告。用户可以右键单击某处并选择“查看报告” - 现在我将报告内容检索到一个临时文件中,并启动处理HTML文件的进程,即默认浏览器。问题是我无法进行清理,即删除临时文件。

0
0 Comments

问题的原因:在调用异步进程并等待其完成时,可能会出现页面加载过快而导致进程无法完成的情况。

解决方法:可以使用

Process

类的

Exited

事件来处理进程完成后的清理工作。如果想要等待进程完成(包括超时等情况),可以使用

WaitForExit

方法。如果想要异步等待进程完成,可以使用不同的线程,例如使用线程池的

QueueUserWorkItem

方法来启动进程,然后等待其完成。

对于问题中提到的情况,如果在主方法中调用了一个带有异步进程的函数,并且在函数执行完之前主方法已经执行完,则页面会加载而不等待进程的完成。解决方法是在主方法中等待线程完成,具体的实现需要根据具体的需求来确定。

另外,如果想要在页面加载时进行文件转换并使用JavaScript播放,可以考虑使用Ajax或轮询来处理进程的完成情况,以避免阻塞原始请求。

关于WaitForExit()方法的作用,它使用WaitHandle来设置超时时间。

至于问题中提到的打开.jpg文件时进程无法退出的情况,可能需要进一步调试和检查代码,确保正确地关闭进程和文件。

0
0 Comments

在.NET 5中引入了新的API Process.WaitForExitAsync,它允许异步等待进程的完成。它与现有的Process.WaitForExit功能相同,唯一的区别是等待是异步的,因此不会阻塞调用线程。

使用示例:

private async void button1_Click(object sender, EventArgs e)

{

string filePath = Path.Combine

(

Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),

Guid.NewGuid().ToString() + ".txt"

);

File.WriteAllText(filePath, "Hello World!");

try

{

using Process process = new();

process.StartInfo.FileName = "Notepad.exe";

process.StartInfo.Arguments = filePath;

process.Start();

await process.WaitForExitAsync();

}

finally

{

File.Delete(filePath);

}

MessageBox.Show("Done!");

}

在上面的示例中,当用户与打开的文件进行交互时,UI保持响应。如果使用WaitForExit而不是WaitForExitAsync,UI线程将被阻塞。

如果我需要在较低版本的.NET上使用这个功能,我可能会将源代码复制到扩展方法中。

如果只涉及启动一个进程,我可能更喜欢使用await Task.Run(() => process.WaitForExit());这种不太优雅但安全的方法。

不,这与阻塞调用WaitForExit()相比没有任何优势,并且还增加了await的额外开销。这是不安全的,请不要这样做。

我不确定你在比较什么。你是说异步的Process.WaitForExitAsync与阻塞的Process.WaitForExit没有任何优势,并且还不安全吗?

我是说await Task.Run(<同步方法>)不是一个好的替代方法,因为它将工作排队到线程池。有关更多详细信息,请参见Stephen Cleary的博客。

如果你想要Process.WaitForExitAsync的功能,并且目标是.NET 5之前的.NET平台,那么在你的意见中有什么更好的替代方法?同步的Process.WaitForExit会阻塞UI线程,导致UI无响应,所以不是一个选择。你必须提供更好的建议。

0
0 Comments

异步进程启动并等待它完成的问题是因为希望在不阻塞任何线程的情况下等待进程退出,并支持超时。为了解决这个问题,可以使用下面的方法:

public static Task WaitForExitAsync(this Process process, TimeSpan timeout)
{
    ManualResetEvent processWaitObject = new ManualResetEvent(false);
    processWaitObject.SafeWaitHandle = new SafeWaitHandle(process.Handle, false);
    TaskCompletionSource tcs = new TaskCompletionSource();
    RegisteredWaitHandle registeredProcessWaitHandle = null;
    registeredProcessWaitHandle = ThreadPool.RegisterWaitForSingleObject(
        processWaitObject,
        delegate(object state, bool timedOut)
        {
            if (!timedOut)
            {
                registeredProcessWaitHandle.Unregister(null);
            }
            processWaitObject.Dispose();
            tcs.SetResult(!timedOut);
        },
        null /* state */,
        timeout,
        true /* executeOnlyOnce */);
    return tcs.Task;
}

与已接受答案相比,这种方法的优势在于不会阻塞任何线程,从而减少应用程序的开销。

0