概述
await/async 关键字组合是C#中异步实现的一种常用方式。
async用于修饰方法,表明该方法为异步方法。但只有async+await的组合才能真正实现异步的执行。若“异步方法”内没有await,则该方法不是异步方法,仍为同步模式。- 由于
await只能用于异步方法中,所以方法必须用async修饰。 - 异步方法的放回类型必须为
void或Task或Task<TResult>中的一种。 - 异步方法内必须含有
await,用于表示异步等待的位置。虽然不太恰当,但有点类似debug中的断点。 await后只能修饰Task或Task<TResult>。(方法的返回类型或变量类型)await task的内容等价于task.Result。await关键字上下的代码有可能处于不同的线程。
说的挺清楚,就是示例代码命名有点长有点绕。
https://www.cnblogs.com/zhaoshujie/p/11192036.html
https://www.cnblogs.com/zhili/archive/2013/05/15/Csharp5asyncandawait.html
死锁
public class AsyncDemo
{
public async void Run()
{
Console.WriteLine($"Demo start\t{Thread.CurrentThread.ManagedThreadId}");
var task = GetAsync();
// await task; // 取消注释则无死锁
string ret = task.Result; // 死锁位置A
Console.WriteLine($"Demo end\t{Thread.CurrentThread.ManagedThreadId}");
}
public async Task<string> GetAsync()
{
Console.WriteLine($"GetAsync start\t{Thread.CurrentThread.ManagedThreadId}");
var task = await Task.Run(() =>
{
Console.WriteLine($"Task start\t{Thread.CurrentThread.ManagedThreadId}");
Thread.Sleep(2000);
Console.WriteLine($"Task end\t{Thread.CurrentThread.ManagedThreadId}");
return "xxxx";
});// 死锁位置B
Console.WriteLine($"GetAsync end\t{Thread.CurrentThread.ManagedThreadId}");
return task;
}
}
死锁状态

取消注释后

死锁的原因在于,两个死锁位置的代码均锁定了共享资源,即阻塞了当前的context。从线程id也可以看出,死锁的时候,GetAsync无法进入GetAsync end 1那一行,因为线程1正被阻塞在位置A。导致task的结果没办法返回线程1,处于等待中,形成了位置B。
注意,如果string ret = task.Result;代码不存在,即不使用task的结果,则两种情况都不会死锁。因为没有出现抢占共享资源的情况。
https://www.cnblogs.com/OpenCoder/p/4434574.html 死锁
https://blog.stephencleary.com/2012/02/async-and-await.html
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

本文详细介绍了C#中await/async关键字的使用方法,包括异步方法的定义、执行流程及死锁原因分析。通过示例代码,阐述了await和async如何协同工作以实现真正的异步执行。
5407

被折叠的 条评论
为什么被折叠?



