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

如您所知,在等待不需要捕获同步上下文的代码中的任务时调​​用Task.ConfigureAwait(false)是一个不错的主意,否则会导致死锁 。

那么,你需要多久才能捕获一个同步上下文呢? 我的做法很less。 在大多数情况下,我正在使用“库”代码,这几乎迫使我一直使用Task.ConfigureAwait(false)

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

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

async / await的其中一个目的是编写响应式GUI程序。 在这种情况下,将某些工作卸载到Task之后返回到UI线程是至关重要的,因为UI更新只能在大多数Windows GUI平台的主线程中发生。 asynchronous/等待有助于GUI开发人员做正确的事情。

这不是默认选项更合理的唯一示例。 我只能推测,但我会怀疑ConfigureAwait默认的决定是基于确保asynchronous工作尽可能less的摩擦,对于微软预计最有用的用例。 不是每个人都写框架。

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

一个不同的默认会导致成千上万的问题,为什么代码不起作用,更糟糕的是,成千上万的答案“微软糟糕的,他们让你写在每个程序中Control.CheckForIllegalCrossThreadCalls = false;为什么是'那默认?“ 而不是实际添加适当的.ConfigureAwait(true)调用。

看看这个链接的第二个解决scheme:

 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线程上执行。

这两个片段看起来像一个人可以合理编写的代码,默认情况下,其中一个必须被打破。 由于死锁与线程不安全访问相比危险性更小,更容易检测,因此selectConfigureAwait(true)作为默认值是更保守的select。