随意使用异步的await和Result,被弄得欲仙欲死,然后看了 Don't Block on Async Code,稍许明白,翻译然后加上自己的理解以加深印象。

会死锁的两个例子

UI例子

    public static async Task<JObject> GetJsonAsync(Uri uri)
{
using (var client = new HttpClient())
{
var jsonString = await client.GetStringAsync(uri);
return JObject.Parse(jsonString);
}
} // My "top-level" method.
public void Button1_Click(...)
{
var jsonTask = GetJsonAsync(...);
textBox1.Text = jsonTask.Result;
}

** ASP.NET例子**

    public static async Task<JObject> GetJsonAsync(Uri uri)
{
using (var client = new HttpClient())
{
var jsonString = await client.GetStringAsync(uri);
return JObject.Parse(jsonString);
}
} // My "top-level" method.
public class MyController : ApiController
{
public string Get()
{
var jsonTask = GetJsonAsync(...);
return jsonTask.Result.ToString();
}
}

死锁的原因

await 一个Task后,当Task完成后将继续一个Context。

UI例子的content是 UI content,ASP.NET例子的Content是request content。在任何时候,这两个content只能属于一个线程,是不能被具体的线程捆绑(tied)。这个有趣或者恶心的特色没被官方文档说明,只在my MSDN article about SynchronizationContext

上面两个例子的运行过程是:

  1. 在UI/ASP.NET context,调用GetJsonAsync方法;
  2. 在UI/ASP.NET context,GetJsonAsync方法调用HttpClient.GetStringAsync开始一个REST请求;
  3. GetStringAsync返回一个未完成的Task,表示REST请求没有完成;
  4. GetJsonAsync等待GetStringAsync返回的Task。当前Context被捕获(保存),当前Context在GetJsonAsync完成时将被调用。GetJsonAsync返回一个未完成的Task,表示GetJsonAsync方法未完成;
  5. jsonTask.Result同步阻塞GetJsonAsync返回的任务,即阻塞context;
  6. ...然后,REST请求完成了,然后通知GetStringAsync方法;
  7. GetStringAsync准备继续任务,他等待context可用,然后他可以在context运行;
  8. 死锁!jsonTask.Result阻塞了context线程,等待GetStringAsync完成,GetStringAsync等待context空闲,然后它可以完成。

防止死锁

两点经验:

  1. 异步方法中,尽可能添加*ConfigureAwait(false) *;
  2. 别阻塞;使用 async

根据第一点经验:

var jsonString = await client.GetStringAsync(uri);

改成

var jsonString = await client.GetStringAsync(uri).ConfigureAwait(false);

根据第二点经验,调用异步方法的代码如下:

    public async void Button1_Click(...)
{
var json = await GetJsonAsync(...);
textBox1.Text = json;
} public class MyController : ApiController
{
public async Task<string> Get()
{
var json = await GetJsonAsync(...);
return json.ToString();
}
}

await 是一个异步等待

.Result是一个同步等待

同步等待在控制台程序、单元测试中不会死锁

【C#】await & Result DeadLock的更多相关文章

  1. 【Lab】提取result的bits和Y-PSNR数据并整理到Excel

    [Lab]提取result的bits和Y-PSNR数据并整理到Excel 更新:使用openpyxl库直接将数据写入Excel中 注意:openpyxl是第三方库,如果没有安装.请命令行里键入pip ...

  2. C#异步的世界【下】

    接上篇:<C#异步的世界[上]> 上篇主要分析了async\await之前的一些异步模式,今天说异步的主要是指C#5的async\await异步.在此为了方便的表述,我们称async\aw ...

  3. 【转】C#异步的世界【下】

    [转]C#异步的世界[下] 接上篇:<C#异步的世界[上]> 上篇主要分析了async\await之前的一些异步模式,今天说异步的主要是指C#5的async\await异步.在此为了方便的 ...

  4. C#异步的世界【下】(转)

    接上篇:<C#异步的世界[上]> 上篇主要分析了async\await之前的一些异步模式,今天说异步的主要是指C#5的async\await异步.在此为了方便的表述,我们称async\aw ...

  5. 【TypeScript】如何在TypeScript中使用async/await,让你的代码更像C#。

    [TypeScript]如何在TypeScript中使用async/await,让你的代码更像C#. async/await 提到这个东西,大家应该都很熟悉.最出名的可能就是C#中的,但也有其它语言也 ...

  6. 【笔记】记一次.net语法await和async的异步编程实验与笔记。

    1.实践代码全记录: using System; using System.Collections.Generic; using System.Diagnostics; using System.Li ...

  7. 【Selenium】【BugList9】windows环境,fp = open("./"+ time.strftime("%Y-%m-%d %H:%M:%S") + " result.html",'wb'),报错:OSError: [Errno 22] Invalid argument: './2018-09-05 10:29:32 result.html'

    [代码] if __name__=="__main__": suite = unittest.TestSuite() suite.addTest(Baidu("test_ ...

  8. 【锁】Oracle死锁(DeadLock)的分类及其模拟

    [锁]Oracle死锁(DeadLock)的分类及其模拟 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不 ...

  9. 【多线程】 Task ,async ,await

    [多线程]Task ,async ,await 一. WinForm 里经常会用到多线程, 多线程的好出就不多说了,来说说多线程比较麻烦的地方 1. UI 线程与其他线程的同步,主要是 Form 和 ...

随机推荐

  1. day4——无重复字符的最长子串

    // 小白一名,0算法基础,艰难尝试算法题中,若您发现本文中错误, 或有其他见解,往不吝赐教,感激不尽,拜谢. 领扣 第2题 今日算法 题干 //给定一个字符串,请你找出其中不含有重复字符的 最长子串 ...

  2. 理解R语言gdistance包下的transition函数

    library(raster)library(gdistance)r <- raster(nrows=3, ncols=4, xmn=0, xmx=7, ymn=0, ymx=6, crs=&q ...

  3. @staticmethod和@classmethod

    一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法. 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用. 这有利于组织代码,把某些应 ...

  4. python 学习笔记 4 ----> dive into python 3

    解析 列表解析.字典解析.集合解析 浏览本地文件系统的模块: 1 os 2 os.path 3 glob os模块:获取(和修改)本地目录.文件进程.环境变量等信息 os.path模块:包含了操作路径 ...

  5. spring boot2 kafka

    一.软件版本 1.linux:centos6 2.zookeeper:zookeeper-3.4.1 3.kafka:kafka_2.12-2.2.0 4.jdk:1.8 5.instelliJ Id ...

  6. 蓝桥杯第六届省赛 手链样式 STL

    小明有3颗红珊瑚,4颗白珊瑚,5颗黄玛瑙.他想用它们串成一圈作为手链,送给女朋友.现在小明想知道:如果考虑手链可以随意转动或翻转,一共可以有多少不同的组合样式呢? 分析:这个题首先一定要理解题意,转动 ...

  7. 关于微信小程序获取当前位置信息

    小程序开发---获取当前位置信息 一.获取用户地理位置信息 1.配置app.json文件 { "pages": ["pages/index/index"], & ...

  8. 小程序批量获取input的输入值,监听输入框,数据同步

    在使用小程序时,跟vue的数据绑定不一样,没有v-model这个属性了,官网也只是给了一些事件监听. 但是我们如果有多个表单时,需要写多个事件来同步数据.这样做很麻烦.下面的方法可以解决,只需要一个方 ...

  9. count性能

    表有主键列,count(1)的效率会稍微高于count(*),count(主键列)效率会高于count(1).表没有主键列,count(1)效率会高于count(*) count(1).count(* ...

  10. 【数论】 快速幂&&矩阵快速幂

    首先复习快速幂 #include<bits/stdc++.h> using namespace std; long long power(long long a,long long b,l ...