在非异步块中 Task.Result 后控制不屈服
Control Not yielding after Task.Result in a non Async Block
我正在试验 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;
}
}
What might be the reason for the same?
区别在于一个死锁,而另一个则没有。当您 await
时,您 异步等待 通过将控制权交还给调用方法。当您使用 Task.Result
时,您会同步阻塞调用。这会导致僵局。
为什么?因为这里涉及到一个叫做 "Synchronization Context" 的东西,它负责在它之前使用的相同上下文中执行你的延续(第一个 await
之后的所有代码)的一些魔法,这在你的案例是 UI 线程 。因为您与 Task.Result
同步阻塞,continuation 无法将自己编组回 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;
}
我正在试验 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;
}
}
What might be the reason for the same?
区别在于一个死锁,而另一个则没有。当您 await
时,您 异步等待 通过将控制权交还给调用方法。当您使用 Task.Result
时,您会同步阻塞调用。这会导致僵局。
为什么?因为这里涉及到一个叫做 "Synchronization Context" 的东西,它负责在它之前使用的相同上下文中执行你的延续(第一个 await
之后的所有代码)的一些魔法,这在你的案例是 UI 线程 。因为您与 Task.Result
同步阻塞,continuation 无法将自己编组回 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;
}