简体   繁体   English

我是否总是需要等待一次性 object 的异步方法而不是返回其任务?

[英]Do I always have to await on an Async method of a disposable object instead of returning its Task?

Seems I fell into a massive gotcha and after hours of debugging I saw that process goes out of "using" scope in RunGame1() and the Task never completes when awaited upon.似乎我陷入了一个巨大的陷阱,经过数小时的调试,我看到该过程在 RunGame1() 中不再“使用” scope,并且在等待时任务永远不会完成。

async void Execute(object o)  // ICommand.Execute
{
    // fire and forget
    try
    {
        await RunGame2();  // RunGame1() fails to complete
    }
    finally
    { ... }
}

// This fails due to process going out of "using" scope and never completes
Task RunGame1()
{
    var info = new ProcessStartInfo("game.exe") { CreateNoWindow = true };
    using var process = new Process() { StartInfo = info };
    process.Start();
    return process.WaitForExitAsync();
}

// Have to await the Task inside the method
async Task RunGame2()
{
    var info = new ProcessStartInfo("game.exe") { CreateNoWindow = true };
    using var process = new Process() { StartInfo = info };
    process.Start();
    await process.WaitForExitAsync();
}

Is there a pattern to get around this so I can return the Task to save the compiler making an extra state machine or is it just something to be aware of?是否有解决此问题的模式,以便我可以返回任务以保存编译器,从而制作额外的 state 机器,或者只是需要注意的事情?

This is a common gotcha indeed - I've seen several bugs due to similar.这确实是一个常见的问题 - 由于类似的原因,我已经看到了几个错误。

In short:简而言之:

  • no , you're not always required to await a task, and sometimes it can be actively advantageous to avoid the overhead of the async machinery - especially in tight code like file/network IO loop, but (and it is a big but),您并不总是需要await任务,有时避免异步机制的开销可能是积极有利的 - 特别是在文件/网络 IO 循环等紧凑代码中,但是(这是一个很大的但是)
  • if that means you're escaping a try / finally region (which also includes using and lock , although there are other bigger problems with lock in async code), then you need to take that into consideration , which usually means "yes, you need to await "如果这意味着您是 escaping 一个try / finally区域(其中还包括usinglock ,尽管在async代码中lock存在其他更大的问题),那么您需要考虑到这一点,这通常意味着“是的,您需要await

It would be nice if there was an analyzer that spotted the return of a Task[<T>] / ValueTask[<T>] in a non- async method, inside such a region, as it is almost always a bug, and for the few times that it isn't (where the finally has nothing to do with the thing being returned) it could be suppressed.如果有一个分析器发现Task[<T>] / ValueTask[<T>]在这样一个区域的非async方法中return ,那就太好了,因为它几乎总是一个错误,并且对于有几次它不是( finally与返回的东西无关)它可以被压制。

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

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