C#异步代码导致阻塞及解决办法

本文讲述了在ASP.NET中,如何避免因混用async和Task.Result引发的线程阻塞问题,方法包括使用ConfigureAwait(false)确保异步操作在其他线程上执行和通过async方法直接获取异步结果,同时提醒注意线程同步上下文的丢失可能导致的线程不安全问题。
摘要由CSDN通过智能技术生成

    在 UI界面或者ASP.NET中调用async的异步代码时如果async和task.Result混用会出现线程被阻塞锁死的情况。

导致阻塞的示例代码:

public static async Task<JObject> GetJsonAsync(Uri uri)
{
  // 请勿在实际使用过程中将 httpclient 放在 using 中,此处仅是示例
  using (var client = new HttpClient())
  {
    var jsonString = await client.GetStringAsync(uri);
    return JObject.Parse(jsonString);
  }
}


public void Button1_Click(...)
{
  var jsonTask = GetJsonAsync(...);
  textBox1.Text = jsonTask.Result;
}

阻止死锁的两种办法:

使用 ConfigureAwait(false)

public static async Task<JObject> GetJsonAsync(Uri uri)
{
  using (var client = new HttpClient())
  {
    var jsonString = await client.GetStringAsync(uri).ConfigureAwait(false);
    return JObject.Parse(jsonString);
  }
}

默认情况下,当您使用async/await时,它将在开始请求的原始线程上继续运行(状态机)。但是,如果当前另一个长时间运行的进程已经接管了该线程,那么你就不得不等待它完成。要避免这个问题,可以使用ConfigureAwait的方法和false参数。当你用这个方法的时候,这将告诉Task它可以在任何可用的线程上恢复自己继续运行,而不是等待最初创建它的线程。这将加快响应速度并避免许多死锁。

但是,当使用此方法后,线程同步上下文将丢失,从而转变成异步操作,如果在之后继续操作界面元素等,会提示线程不安全。

使用 Async 方法进行调用

public async void Button1_Click(...)
{
  var json = await GetJsonAsync(...);
  textBox1.Text = json;
}

原文链接地址:https://blog.exsvc.cn/article/csharp-async-deadlock.html

5e3c6a0b5a28238909d7b8bf7cf2b8c2.png

- EOF -

技术群:添加小编微信dotnet999

公众号:Dotnet讲堂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值