我遇到了一些使用c#的async/ await关键字进行异步编程的最佳实践(我是c#5.0的新手)。
async
await
给出的建议之一如下:
稳定性:了解您的同步上下文
…某些同步上下文是不可重入的和单线程的。这意味着在给定时间只能在上下文中执行一个工作单元。Windows UI线程或ASP.NET请求上下文就是一个例子。在这些单线程同步上下文中,很容易使自己陷入僵局。如果您从单线程上下文中生成任务,然后在上下文中等待该任务,则您的等待代码可能会阻止后台任务。
public ActionResult ActionAsync() { // DEADLOCK: this blocks on the async task var data = GetDataAsync().Result; return View(data); } private async Task<string> GetDataAsync() { // a very simple async method var result = await MyWebService.GetDataAsync(); return result.ToString(); }
如果我自己剖析,则主线程会生成一个新线程MyWebService.GetDataAsync();,但是由于主线程在此等待,因此它将在中等待结果GetDataAsync().Result。同时,说数据准备好了。为什么主线程不继续其继续逻辑并从中返回字符串结果GetDataAsync()?
MyWebService.GetDataAsync();
GetDataAsync().Result
GetDataAsync()
有人可以解释一下为什么上面的示例中出现死锁吗?我完全不知道问题是什么…
看一下这个例子,Stephen为您提供了一个清晰的答案:
因此,这是从顶级方法(Button1_Click对于UI / MyController.Get对于ASP.NET)开始的事情: 顶级方法调用GetJsonAsync(在UI / ASP.NET上下文中)。 GetJsonAsync通过调用HttpClient.GetStringAsync(仍在上下文中)启动REST请求。 GetStringAsync返回uncompleted Task,指示REST请求未完成。 4. GetJsonAsync等待的Task归还GetStringAsync。上下文被捕获,以后将用于继续运行该GetJsonAsync方法。GetJsonAsync返回uncompleted Task,指示该GetJsonAsync方法不完整。 顶级方法同步阻止Task返回的GetJsonAsync。这将阻塞上下文线程。 …最终,REST请求将完成。这样就完成了Task由返回的GetStringAsync。 GetJsonAsync现在,可以继续运行for的延续,它等待上下文可用,以便可以在上下文中执行。 死锁 。顶级方法正在阻止上下文线程,等待GetJsonAsync完成,并且GetJsonAsync正在等待上下文空闲以便可以完成。对于UI示例,“上下文”是UI上下文。对于ASP.NET示例,“上下文”是ASP.NET请求上下文。这种死锁可能是由于“上下文”引起的。
因此,这是从顶级方法(Button1_Click对于UI / MyController.Get对于ASP.NET)开始的事情:
Button1_Click
MyController.Get
顶级方法调用GetJsonAsync(在UI / ASP.NET上下文中)。
GetJsonAsync
GetJsonAsync通过调用HttpClient.GetStringAsync(仍在上下文中)启动REST请求。
HttpClient.GetStringAsync
GetStringAsync返回uncompleted Task,指示REST请求未完成。
GetStringAsync
Task
4. GetJsonAsync等待的Task归还GetStringAsync。上下文被捕获,以后将用于继续运行该GetJsonAsync方法。GetJsonAsync返回uncompleted Task,指示该GetJsonAsync方法不完整。
顶级方法同步阻止Task返回的GetJsonAsync。这将阻塞上下文线程。
…最终,REST请求将完成。这样就完成了Task由返回的GetStringAsync。
GetJsonAsync现在,可以继续运行for的延续,它等待上下文可用,以便可以在上下文中执行。
死锁 。顶级方法正在阻止上下文线程,等待GetJsonAsync完成,并且GetJsonAsync正在等待上下文空闲以便可以完成。对于UI示例,“上下文”是UI上下文。对于ASP.NET示例,“上下文”是ASP.NET请求上下文。这种死锁可能是由于“上下文”引起的。
您应该阅读另一个链接: 等待,UI和死锁! 天啊!