为什么ConfigureAwait(false)不是默认选项?

时间:2014-10-31 18:37:35

标签: c# async-await

如您所知,在等待不需要捕获同步上下文的代码中的任务时调​​用Task.ConfigureAwait(false)是个好主意,因为否则它可以cause deadlocks。 / p>

那么,您需要多久捕获一次同步上下文?我的练习,很少。在大多数情况下,我正在使用“库”代码,这几乎迫使我一直使用Task.ConfigureAwait(false)

所以我的问题非常简单:为什么Task.ConfigureAwait(false)不是任务的默认选项?强制“高级”代码使用Task.ConfigureAwait(true)不是更好吗?这有历史原因,还是我错过了什么?

3 个答案:

答案 0 :(得分:14)

.ConfigureAwait(false)一起使用的大多数代码也可以使用.ConfigureAwait(true),但效果不理想。是的,不是所有代码,但仍然是最多的。当前默认设置允许最高百分比的代码工作,而无需修改典型程序员遗憾无法理解的设置。

一个不同的默认值只会导致成千上万的关于代码无法运行的问题,更糟糕的是,成千上万的答案以微软的形式糟透了,他们让你在每个人写Control.CheckForIllegalCrossThreadCalls = false;程序。为什么不是默认的?"而不是实际添加适当的.ConfigureAwait(true)电话。

答案 1 :(得分:9)

仅仅因为你的典型用例需要ConfigureAwait(false),它并不意味着它是"正确的"或最常用的选项。

async / await的设计之一就是编写响应式GUI程序。在这种情况下,在将一些工作卸载到Task之后返回UI线程是至关重要的,因为UI更新只能从大多数Windows GUI平台上的主线程发生。 Async / await帮助GUI开发人员做正确的事情。

这不是默认选项更有意义的唯一示例。我只能推测,但我怀疑对ConfigureAwait默认的决定是基于确保异步对尽可能少的摩擦起作用,对于Microsoft预期它将被最多使用的用例。不是每个人都在编写框架。

答案 2 :(得分:8)

从该链接查看第二个示例解决方案:

public async void Button1_Click(...)
{
  var json = await GetJsonAsync(...);
  textBox1.Text = json;
}

public class MyController : ApiController
{
  public async Task<string> Get()
  {
    var json = await GetJsonAsync(...);
    return json.ToString();
  }
}

如果默认行为是ConfigureAwait(false),则textBox1.Text = json;语句将在随机线程池线程而不是UI线程上执行。

两个片段看起来都像某人可以合理写的代码,默认情况下,其中一个片段必须被破坏。由于死锁比线程不安全的访问危险性更小且更易于检测,因此选择ConfigureAwait(true)作为默认选择是更保守的选择。