C# 在不等待的情况下返回异步方法的结果-坏主意?

C# 在不等待的情况下返回异步方法的结果-坏主意?,c#,asynchronous,async-await,C#,Asynchronous,Async Await,我正在看前一段时间写的一些代码,这让我非常紧张。提问方法的一般形式是这样的 public Task Foo(...){ SyncMethod(); SyncMethod(); ... return AsyncMethod(); } 我意识到我可以在最后一次调用中标记方法async并执行wait,但是……我必须这样做吗?按原样使用安全吗?在最后一个async方法之前调用的sync方法没有异步替代方法,并且Foo方法不关心asynchmethod的结果,因此看起来只需将

我正在看前一段时间写的一些代码,这让我非常紧张。提问方法的一般形式是这样的

public Task Foo(...){

   SyncMethod();
   SyncMethod();
   ...
   return AsyncMethod();

}
我意识到我可以在最后一次调用中标记方法
async
并执行
wait
,但是……我必须这样做吗?按原样使用安全吗?在最后一个
async
方法之前调用的sync方法没有异步替代方法,并且Foo方法不关心asynchmethod的结果,因此看起来只需将等待的返回给调用方并让调用方处理就可以了

另外,FWIW,所讨论的代码可能是从一个运行在活动ASP.NET上下文中的线程调用的,所以我的大脑中有一种刺痛的感觉,我在这里没有看到一些看不见的邪恶

我意识到我可以在最后一次调用中标记方法
async
并执行
wait
,但是……我必须这样做吗

实际上,如果您这样做了,它唯一的变化是,由这些同步方法中的任何一个引发的异常都将被包装到返回的
任务中,而在当前实现中,该方法将引发异常,而不会成功返回
任务。同步工作和异步工作的实际效果完全不受影响

话虽如此,你提到的两种选择都令人担忧。这里有一个方法看起来是异步的,这意味着调用它的人希望它或多或少立即返回,但实际上该方法将同步运行一段时间

如果您的两个同步方法非常快,因此,您确信这非常少量的同步工作不会引起任何调用方的注意,那么这很好。然而,如果这项工作(甚至可能)需要花费大量的时间来解决,那么你就有问题了


为这些方法提供实际的异步替代方法是最好的,但作为最后的手段,在您有更好的选择之前,通常您能做的最好的事情是
等待Task.Run(()=>SyncMethod())async
)。

Nice。请注意,“唯一的改变…”并不是完全正确的-标记方法
async
也会显著改变方法的代码生成方式(线性与状态机),这可能是一些性能关键情况引起的问题。@AlexeiLevenkov,这是实现细节发生重大变化这一事实的唯一可见效果。虽然技术上存在性能成本,但该成本非常小;编写一个真正能够看到它的应用程序非常困难。特别是,在处理异步操作时,您天生就是在处理耗时较长的事情。预期在微秒内运行的代码一开始不会是异步的,因此在几乎所有情况下,使方法异步的“成本”都相形见绌,甚至无法测量。@Servy,感谢您的精彩解释!我一直忘了传统任务模型和新的异步/等待模型之间异常的抛出/处理有什么不同,也感谢您的提醒。除了关于
任务。运行
的部分外,答案不错。我认为更好的选择是直接调用同步(可能是阻塞)方法,并记录该方法可能阻塞的内容,即使它具有异步签名。避免
Task.Run
在ASP.NET上特别重要。@StephenCleary好吧,有一个方法的API表明它是异步的,但仍然会阻塞相当长的时间,这仍然是我非常关心的问题,因为它很容易导致难以诊断的问题。将代码重构为多个方法,一个同步,一个异步,将是另一种选择。我只是没有看到大多数人在使用它之前阅读每个方法的文档,而是主要根据它的签名来解释它的功能和工作方式。