C# 使异步函数同步的后果

C# 使异步函数同步的后果,c#,async-await,C#,Async Await,(如果问题的某些部分被认为“太基本”,我提前表示歉意。我已经做了关于async await的研究,但对我来说,这不是一个容易理解的概念。要么这样,要么我没有找到合适的资源。) 我总是读到(或者我就是这么解释的)“异步调用同步的方法是将‘wait’放在前面” 因此,该语句产生的代码如下所示: // CODE 1: public void async MyFunction() { await SomeFunctionAsync(); } 也就是说:1)将await放在异步函数前面,2)将A

(如果问题的某些部分被认为“太基本”,我提前表示歉意。我已经做了关于async await的研究,但对我来说,这不是一个容易理解的概念。要么这样,要么我没有找到合适的资源。)

我总是读到(或者我就是这么解释的)“异步调用同步的方法是将‘wait’放在前面”

因此,该语句产生的代码如下所示:

// CODE 1:
public void async MyFunction()
{
    await SomeFunctionAsync();
}
也就是说:1)将
await
放在异步函数前面,2)将
Async
放在函数中,因为现在它包含
await

但根据我的经验,有时行为有点“滑稽”。我注意到的症状是,有时它的行为就像一根逃脱我控制的线

因此第一个问题是:当调用
MyFunction()
并且该函数包含
async
关键字时会发生什么?我的理解是(足够令人困惑)它不应该被称为
myfunctionsync()
,因为它是为返回
任务的函数保留的

…因此,我提出的另一种选择(其行为似乎与同步类一致)是以下类型的代码:

// CODE 2:
public void MyFunction()
{
    var task = SomeFunctionAsync();
    Task.WaitAll(task);
}
第二个问题:有人能解释一下
代码2的缺点(如果有的话)

另外,隐含的问题是,我有兴趣了解我对异步等待模式可能存在的任何误解

我总是读到(或者我就是这么解释的)“异步调用同步的方法是将‘wait’放在前面”

一点也不。这是调用异步代码的串行方式,但不是同步方式。“同步”表示“阻塞当前线程,
wait
不会阻塞当前线程。但是,“serial”的意思是“在下一件事之前做这件事”,而
wait
会这样做。有关更多信息,请参阅我的

使用
wait
是调用异步方法最自然、最常见的方法。请注意,通常在向方法添加
async
时,还应将返回类型从
void
更改为
Task
。编译器将在这方面为您提供指导:如果您只是将
wait
放入而没有
async
,它将非常明确地为您建议下一个更改

但根据我的经验,有时行为有点“滑稽”。我注意到的症状是,有时它的行为就像一根逃脱我控制的线

这是因为您的代码使用的是
async void
,而不是
async Task
<代码>异步无效
不自然;您没有“控制权”,因为您没有返回
任务
。更自然的方法是使方法
异步任务
,并
等待调用方发出该任务,依此类推。
async
像这样在堆栈中“增长”是很自然的—我们称之为“”


所以第一个问题是:当调用MyFunction()并且该函数包含async关键字时会发生什么?我的理解是(令人困惑的是)它不应该被称为MyFunctionSync(),因为它是为返回任务的函数保留的

您对命名的理解是正确的
MyFunction
不是自然的(
Task
-返回)异步方法

async void
方法非常奇怪,其行为与普通的
async
方法不同。他们古怪的行为是我推荐他们的原因之一。但是既然你问了

async void
方法中的
await
就像常规
async
方法中的
await
一样工作(如我在
async
简介中所述):它将捕获当前上下文(当前的
SynchronizationContext
TaskScheduler
,并在异步操作完成时在该上下文中继续执行
async void
方法。这就是为什么它的行为像一个“无法控制的线程”-只要需要,它就会继续执行。您无法检测它何时完成,因为该方法返回的是
void
,而不是
Task

异常是事情变得更加奇怪的地方。
async void
方法在执行开始时捕获当前的
SynchronizationContext
,如果异常逃逸了
async void
方法,它将在捕获的
SynchronizationContext
上重新引发该异常。这通常会导致p进程级崩溃

第二个问题:有人能解释代码2的缺点(如果有的话)吗

它很容易导致我在博客上描述的异常。它还将任务中的任何异常包装在
aggregateeexception

底线是:不要阻止异步代码。如果你打算阻止它,那么为什么首先要让它异步呢?任何混合的阻止和异步代码都应该被视为具有相当高优先级的技术债务。没有一种解决方案可以在所有情况下都有效,但是有各种各样的黑客可以临时使用在将代码升级为正确的异步时,我在上一篇文章中描述了它们

我总是读到(或者我就是这么解释的)“异步调用同步的方法是将‘wait’放在前面”

一点也不。这是调用异步代码的串行方式,但不是同步方式。“同步”表示“阻止当前线程”,而
await
不会阻止当前线程。但是,“串行”表示“在下一件事之前执行此操作”,而
await
将执行此操作。有关更多信息,请参阅我的

使用
await
是调用异步方法的最自然、最常见的方法。请注意,通常在将
async
添加到