如何和何时使用 "async" 和 "await"
如何和何时使用 "async" 和 "await"
从我的理解来看,async
和await
的主要作用之一是使代码易于编写和阅读-但使用它们是否等同于生成后台线程来执行长时间的逻辑?
我目前正在尝试最基本的示例。我已经添加了一些内联注释。您能为我澄清吗?
// I don't understand why this method must be marked as `async`. private async void button1_Click(object sender, EventArgs e) { Task access = DoSomethingAsync(); // task independent stuff here // this line is reached after the 5 seconds sleep from // DoSomethingAsync() method. Shouldn't it be reached immediately? int a = 1; // from my understanding the waiting should be done here. int x = await access; } async Task DoSomethingAsync() { // is this executed on a background thread? System.Threading.Thread.Sleep(5000); return 1; }
根据我的理解,async和await的主要作用之一是使代码易于编写和阅读。
是的,它们是为了使异步代码易于编写和阅读。
这和生成后台线程来执行长时间逻辑的操作是一样的吗?
完全不是。
//我不明白为什么这个方法必须标记为'async'。
async
关键字启用await
关键字。因此,任何使用await
的方法都必须标记为async
。
//这一行在从DoSomethingAsync()方法的5秒睡眠后到达。它不应该立即到达吗?
不,因为默认情况下async
方法不在另一个线程上运行。
//这是在后台线程上执行的吗?
不是。
您可能会发现我介绍的 async
/await
有所帮助。官方的 MSDN 文档也非常好(特别是 TAP 部分),而 async
团队发布了一份优秀的 FAQ。
使用async
和await
时,编译器会在后台生成一个状态机。
下面是一个示例,我希望能在其中解释一些正在进行的高级细节:
public async Task MyMethodAsync() { TasklongRunningTask = LongRunningOperationAsync(); // independent work which doesn't need the result of LongRunningOperationAsync can be done here //and now we call await on the task int result = await longRunningTask; //use the result Console.WriteLine(result); } public async Task LongRunningOperationAsync() // assume we return an int from this long running operation { await Task.Delay(1000); // 1 second delay return 1; }
好的,那么这里会发生什么:
-
Task
开始执行longRunningTask = LongRunningOperationAsync(); LongRunningOperation
-
假设在主线程(线程ID = 1)上独立进行工作,然后到达
await longRunningTask
。现在,如果
longRunningTask
尚未完成并且仍在运行,则MyMethodAsync()
将返回其调用方法,因此主线程不会被阻塞。当longRunningTask
完成时,线程池中的线程(可以是任何线程)将返回到MyMethodAsync()
的上下文中并继续执行(在本例中将结果打印到控制台)。
第二种情况是longRunningTask
已经完成了执行并且结果可用。当到达await longRunningTask
时,我们已经有了结果,因此代码将在同一线程上继续执行(在本例中将结果打印到控制台)。当然,对于上面的示例,其中涉及Task.Delay(1000)
,情况并非如此。