导致死锁的例子代码:
public static async Task<string> GetWebPageAsync(string uri)
{
//这里的 client 是全局初始化的 HttpClient 对象
return = await client.GetStringAsync(uri);
}
public void Button1_Click(object sender, EventArg e)
{
var webTask = GetWebPageAsync("_get_url_");
textBox1.Text = webTask.Result;
}
{
//这里的 client 是全局初始化的 HttpClient 对象
return = await client.GetStringAsync(uri);
}
public void Button1_Click(object sender, EventArg e)
{
var webTask = GetWebPageAsync("_get_url_");
textBox1.Text = webTask.Result;
}
阻止死锁的两种办法:
一、使用 ConfigureAwait(false)
二、使用 异步Async 方法进行调用:
public static async Task<string> GetWebPageAsync(string uri)
{
//这里的 client 是全局初始化的 HttpClient 对象
return = await client.GetStringAsync(uri).ConfigureAwait(false);
}
{
//这里的 client 是全局初始化的 HttpClient 对象
return = await client.GetStringAsync(uri).ConfigureAwait(false);
}
默认情况下,当您使用async/await时,它将在开始请求的原始线程上继续运行(状态机)。但是,如果当前另一个长时间运行的进程已经接管了该线程,那么你就不得不等待它完成。要避免这个问题,可以使用ConfigureAwait的方法和false参数。当你用这个方法的时候,这将告诉Task它可以在任何可用的线程上恢复自己继续运行,而不是等待最初创建它的线程。这将加快响应速度并避免许多死锁。
但是,当使用此方法后,线程同步上下文将丢失,从而转变成异步操作,如果在之后继续操作界面元素等,会提示线程不安全。
二、使用 异步Async 方法进行调用:
public async void Button1_Click(object sender, EventArg e)
{
var webTask = GetWebPageAsync("_get_url_");
textBox1.Text = webTask.Result;
}
{
var webTask = GetWebPageAsync("_get_url_");
textBox1.Text = webTask.Result;
}