如果每个async都有一个await并且每个await都应用于异步,那么这将在何处以及如何结束?

时间:2017-03-17 09:07:51

标签: c# .net asynchronous async-await

我刚刚介绍了这个概念,如果答案很简单,那么道歉。

我理解async只是一个标志,表示方法中有await,并且当异步方法正在执行其工作时,控件将返回调用方。我的理解是,假设调用堆栈中的某个地方没有等待异步方法,而不是至少立即(即在执行异步方法时完成其他一些工作),这是有用的。

但是,await似乎仅适用于async方法,而await方法内部必须包含{{1}}。这创造了无穷无尽的呼叫链。它必须在某处结束,等待应用于非异步方法。但在哪里?

2 个答案:

答案 0 :(得分:4)

  

然而,await似乎只适用于异步方法,而异步方法又必须等待内部。

从技术上讲,await不适用于方法。发生的方法是调用该方法并返回一些内容(例如Task),然后await应用于该任务

所以,误解在于:await适用于等待物(例如,任务),而不是方法。

  

它必须以某种方式结束,等待应用于非异步方法。

烨。任何方法都可以返回Task(或任何等待的),无论是async还是async。一个方法可以使用TaskFactory.FromAsync来构造它的任务(大多数方法我们写这样做),但它也可以直接构建一个。通常,低级异步方法使用TaskCompletionSource<T>srand()来创建他们返回的任务。

答案 1 :(得分:-1)

它最终会出现在您正在使用的最高层以及您不想阻止的层上。我们假设你有一个Winforms应用程序。这里的所有方法都会在某种情况下结束,这将是异步链的结束。

例如:

private async Task DoSomethingAsync()
{
   await DbClass.GetSomeItemsFromDbAsync();
}

public partial class MyForm : Form
{
   private async void btButton_Click(object sender, EventArgs e)
   {
      await DoSomethingAsync();
   }
}

如果您在示例中看到,我们有一个异步方法。在Button的Click-Event中调用此方法。因此,事件监听器被标记为异步,但不能从其他任何东西调用。在这里,您离开您的链并到达终点。表格不会阻止,这就是我们想要实现的目标。

如果您考虑使用GUI,所有方法都会以事件结束,因为整个程序都是事件驱动的。在Console App中,Endpoint将是Main-Method。在那里你不会将返回类型从void更改为Task,这将停止你的异步链,因为无法等待void。

我希望这可以帮助您理解链条。