我正在尝试使用MSDN示例。我遇到了以下问题。从具有async
模式的按钮单击事件处理程序运行async
代码块时,它可以正常工作(button1_Click
)。但是对于button2_Click
,控件不会超过TaskObj.Result
。可能是什么原因?
private async void button1_Click(object sender, EventArgs e)//this works fine
{
Task<int> TaskObj = AccessTheWebAsync();
string a ="I came here..";
int y = await TaskObj;
string a1 = "I came here also..";
}
private void button2_Click(object sender, EventArgs e)//this is not working
{
Task<int> TaskObj = AccessTheWebAsync();
string a = "I came here..";//control yielded here
int y = TaskObj.Result;//something happened here
string a1 = "Why I couldn't come here?";//why control is not reaching here?
}
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
DoIndependentWork();
string urlContents = await getStringTask;
return urlContents.Length;
}
private void DoIndependentWork()
{
IList<Int32>intK = Enumerable.Range(1, 100000000).ToList();
foreach (int x in intK)
{
int y = x * 2;
}
}
答案 0 :(得分:4)
可能是什么原因?
差异是一个死锁,而另一个不是。当您await
时,您通过将控制权交还给调用方法来异步等待。使用Task.Result
时,您会同步阻止呼叫。这导致僵局。
为什么呢?因为有一种称为&#34;同步上下文&#34;这里涉及到,它负责在之前使用的相同上下文中执行延续(第一个await
之后的所有代码)的一些魔力,在您的情况下是 UI线程。因为你与Task.Result
同步阻塞,所以延续无法将自己编组回UI线程,因为它正在.Result
等待它自己。
相反,请使用await
与之前的按钮点击一样:
private async void button2_Click(object sender, EventArgs e)//this is not working
{
Task<int> TaskObj = AccessTheWebAsync();
string a = "I came here..";//control yielded here
int y = await TaskObj;
}