Roy*_*mir 6 .net c# task-parallel-library async-await
我读了这篇文章,了解Task.ConfigureAwait哪些可以帮助防止异步代码中的死锁.
看看这段代码:( 我知道我不应该这样做.Result,但这是问题的一部分)
private void Button_Click(object sender, RoutedEventArgs e)
{
string result = GetPageStatus().Result;
Textbox.Text = result;
}
public async Task<string> GetPageStatus()
{
using (var httpClient = new HttpClient())
{
var response = await httpClient.GetAsync("http://www.google.com");
return response.StatusCode.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
这将导致死锁,因为:
然后.Result- 操作将在等待异步操作完成时阻止当前线程(即UI线程).
一旦网络调用完成,它将尝试继续response.StatusCode.ToString()在捕获的上下文上执行- 方法.(被封锁 - 因此死锁).
一种解决方案是使用:
var response = await httpClient.GetAsync("http://www.google.com").ConfigureAwait(false);
但其他解决方案是一直异步(没有阻塞):
/*1*/ private async void Button_Click(object sender, RoutedEventArgs e)
/*2*/ {
/*3*/ string result = await GetPageStatus();
/*4*/ Textbox.Text = result;
/*5*/ }
/*6*/ public async Task<string> GetPageStatus()
/*7*/ {
/*8*/ using (var httpClient = new HttpClient())
/*9*/ {
/*10*/ var response = await httpClient.GetAsync("http://www.google.com");
/*11*/ return response.StatusCode.ToString();
/*12*/ }
/*13*/ }
Run Code Online (Sandbox Code Playgroud)
题 :
(我试图了解这段代码如何帮助解决问题 - 通过上下文POV).
线#3和线是否#10捕获不同的上下文?
关于流动的方式,我认为是正确的:
第3行调用#6(调用#10)并看到它还没有完成,所以它等待(#3 = UI线程的捕获上下文).
稍后,第10行在完成后捕获另一个上下文(我将其称为newContext),它返回"newContext"然后释放UI上下文(线程).
我是对的吗?

没有不同的上下文。在这两种情况下,SyncrhonizationContext都是单线程 UI 同步上下文(只要您不使用ConfigureAwait(false))
当 UI 线程同步等待自身时,就会发生死锁。您可以通过避免 UI 线程ConfigureAwait(false)或不阻止它来解决这个问题Task.Result。
“async一路走下去”解决死锁的原因是UI线程不再被阻塞并且可以自由地运行两者的延续\xd7\x93async操作的延续\xd7\x93。
所以:
\n\nSyncrhonizationContext。#11后,线路将在 UI 线程(未阻塞)上恢复,GetAsync从而完成GetPageStatus任务。然后线#4也会在 UI 线程上恢复。重要的是要理解SynchronizationContext在这种情况下,仅确保某些工作将由专用线程(串行)完成。只要线程可以自由地执行该工作单元,就永远不会发生死锁。
| 归档时间: |
|
| 查看次数: |
334 次 |
| 最近记录: |