调用Task.Result时Windows窗体中断

时间:2014-04-12 21:02:43

标签: c# winforms async-await

我的代码类似于以下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窗体上的事件处理程序调用它的函数时,它会中断并且不响应。

为什么会这样?我该如何解决?

2 个答案:

答案 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