【问题标题】:process.WaitForExit(int32) asynchronouslyprocess.WaitForExit(int32) 异步
【发布时间】:2016-08-01 10:44:44
【问题描述】:

我正在使用https://stackoverflow.com/a/19104345/2713516 中提供的解决方案来运行 WaitForExit 异步,但是,我想使用 Int32 参数重载 (https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx),如 process.WaitForExit(10000)。

如何更改此扩展方法以使其与超时参数一起使用?

附带问题:我还看到有人提到 (https://stackoverflow.com/a/32994778/2713516) 我应该在某个时候处理 cancelToken,那么我不应该在方法中使用 dispose/using 吗?以及如何?

/// <summary>
/// Waits asynchronously for the process to exit.
/// </summary>
/// <param name="process">The process to wait for cancellation.</param>
/// <param name="cancellationToken">A cancellation token. If invoked, the task will return 
/// immediately as canceled.</param>
/// <returns>A Task representing waiting for the process to end.</returns>
public static Task WaitForExitAsync(this Process process, 
    CancellationToken cancellationToken = default(CancellationToken))
{
    var tcs = new TaskCompletionSource<object>();
    process.EnableRaisingEvents = true;
    process.Exited += (sender, args) => tcs.TrySetResult(null);
    if(cancellationToken != default(CancellationToken))
        cancellationToken.Register(tcs.SetCanceled);

    return tcs.Task;
}

【问题讨论】:

  • 您可以使用stackoverflow.com/questions/25683980/…中的“无内置超时”模式
  • 你已经传递了CancellationToken - 这已经比超时更有用了。超时后取消,例如new CancellationTokenSource(timeout).Token.
  • 感谢您的建议

标签: c# .net async-await extension-methods


【解决方案1】:

您需要更改方法签名并应用流程本身的结果。例如考虑以下内容:

/// <summary>
/// Waits asynchronously for the process to exit.
/// </summary>
/// <param name="process">The process to wait for cancellation.</param>
/// <param name="cancellationToken">A cancellation token. If invoked, the task will return 
/// immediately as canceled.</param>
/// <returns>A Task representing waiting for the process to end.</returns>
public static Task WaitForExitAsync(this Process process, 
    int milliseconds,
    CancellationToken cancellationToken = default(CancellationToken))
{
    if (process.HasExited)
    {
        return Task.CompletedTask;
    }

    var tcs = new TaskCompletionSource<object>();
    process.EnableRaisingEvents = true;
    process.Exited += (sender, args) => tcs.TrySetResult(null);
    if (cancellationToken != default(CancellationToken))
    {
        cancellationToken.Register(tcs.SetCanceled);
    }

    return process.HasExited
        ? Task.CompletedTask
        : Task.WhenAny(tcs.Task, Task.Delay(milliseconds));
}

现在,如果进程还没有结束,任务仍然会在延迟后返回。另一种方法是使用Task.Run 调用所需的重载,如下所示:

/// <summary>
/// Waits asynchronously for the process to exit.
/// </summary>
/// <param name="process">The process to wait for cancellation.</param>
/// <param name="cancellationToken">A cancellation token. If invoked, the task will return 
/// immediately as canceled.</param>
/// <returns>A Task representing waiting for the process to end.</returns>
public static Task WaitForExitAsync(this Process process, 
    int milliseconds,
    CancellationToken cancellationToken = default(CancellationToken)) =>
    process.HasExited
        ? Task.CompletedTask
        : Task.Run(() => process.WaitForExit(milliseconds), cancellationToken);
}

【讨论】:

  • 如果进程在添加事件处理程序之前退出,这将不起作用。
  • 嗨@ygoe - 我更新了它来处理这个问题。现在注意.HasExited的用法
  • 如果在您检查了.HasExited,但在您连接事件处理程序之前进程退出了怎么办?
  • 我将此作为社区帖子回复,如果您认为合适,请随时更新。
猜你喜欢
  • 1970-01-01
  • 2010-10-02
  • 1970-01-01
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多