我的代码类似于以下Windows窗体中的代码:
private async Task<string> GetGreetingAsync()
{
return await Task.Run(() => "Hello");
}
private void button1_Click(object sender, EventArgs e)
{
var x = GetGreetingAsync().Result;
}
单击该按钮会导致整个Windows窗体冻结并无响应。没有例外。
即使我没有在事件处理程序中直接使用任务.Result
,并且整个async
标记的代码位于某个类库函数中,该函数提供的接口没有async
,问题仍然存在。这种类库的单元测试没有任何问题,但是当我从Windows窗体上的事件处理程序调用它的函数时,它会中断并且不响应。
为什么会这样?我该如何解决?
答案 0 :(得分:9)
您使用.Result;
阻止了该UI主题(请参阅ConfigureAwait
)
private async Task<string> GetGreetingAsync()
{
return await Task.Run(() => "Hello").ConfigureAwait(false);
}
private void button1_Click(object sender, EventArgs e)
{
var x = GetGreetingAsync().Result;
}
或一路走异步
private async Task<string> GetGreetingAsync()
{
return await Task.Run(() => "Hello");
}
async private void button1_Click(object sender, EventArgs e)
{
var x = await GetGreetingAsync();
}
使用此版本,您甚至无需在GetGreetingAsync
private Task<string> GetGreetingAsync()
{
return Task.Run(() => "Hello");
}
async private void button1_Click(object sender, EventArgs e)
{
var x = await GetGreetingAsync();
}
答案 1 :(得分:0)
您应该在await
上使用Result
而不是Task<T>
来获取非阻止行为。
private async void button1_Click(object sender, EventArgs e)
{
var x = await GetGreetingAsync();
}
调用Result
会导致代码等到Task
完成后调用await
允许使用异步行为。
修改强>
如果您正在执行
,请再次查看您的代码private async Task<string> GetGreetingAsync()
{
return await new Task<string>(() => "Hello");
}
真的不需要。该块可以只是
private Task<string> GetGreetingAsync()
{
return new Task<string>(() => "Hello");
}
没有必要将任务返回async
。