我是否总是必须等待一次性对象的异步方法而不是返回其任务?

c#

似乎我陷入了一个巨大的陷阱,经过数小时的调试,我看到该过程超出了 RunGame1() 中的“使用”范围,并且任务在等待时从未完成。

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();
}

是否有解决此问题的模式,以便我可以返回 Task 以保存编译器制作额外的状态机,还是只是需要注意的事情?

回答

这确实是一个常见的问题 - 由于相似,我已经看到了几个错误。

简而言之:

  • ,您并不总是需要执行await任务,有时避免异步机制的开销可能会非常有利 - 特别是在像文件/网络 IO 循环这样的紧凑代码中,但是(而且它是一个很大的但是)
  • 如果这意味着你逸出try/finally地区(也包括usinglock,虽然有其他更大的问题与lockasync代码),那么你需要考虑到这一点,这通常意味着“是的,你需要await

如果有一个分析器这样的区域发现非方法return中的Task[<T>]/会很好,因为它几乎总是一个错误,并且有几次它不是(那里没有什么可处理被退回的东西)它可以被压制。ValueTask[<T>]asyncfinally


以上是我是否总是必须等待一次性对象的异步方法而不是返回其任务?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>