Почему ConfigureAwait (false) не является параметром по умолчанию?
Как вы знаете, это хорошая идея называть Task.ConfigureAwait(false)
, когда вы ожидаете задачи в коде, который не требует захвата контекста синхронизации, поскольку он может вызывают взаимоблокировки в противном случае.
Хорошо, как часто вам нужно фиксировать контекст синхронизации? Я очень редко использую эту практику. В большинстве случаев я работаю с "библиотечным" кодом, который в значительной степени заставляет меня использовать Task.ConfigureAwait(false)
все время.
Итак, мой вопрос довольно прост: почему Task.ConfigureAwait(false)
не является параметром по умолчанию для задачи? Не было бы намного лучше заставить "высокоуровневый" код использовать Task.ConfigureAwait(true)
? Есть ли историческая причина для этого, или я чего-то не хватает?
Ответы
Ответ 1
Просто потому, что для типичного варианта использования вашего требуется ConfigureAwait (false), это не значит, что это "правильный" или наиболее используемый вариант.
Одна из задач async/await предназначена для написания гибких графических программ. В таких случаях возврат к потоку пользовательского интерфейса после разгрузки какой-либо работы в задачу имеет решающее значение, поскольку обновления пользовательского интерфейса могут произойти только из основного потока на большинстве платформ Windows GUI. Async/await помогает разработчикам графического интерфейса делать правильные вещи.
Это не единственный пример, когда опция по умолчанию имеет смысл. Я могу только догадываться, но я подозреваю, что решение для ConfigureAwait по умолчанию основано на том, что async работает с минимальным трением, насколько это возможно, для случаев использования, которые Microsoft ожидает, что он будет использоваться для большинства. Не каждый пишет фреймворки.
Ответ 2
Большая часть кода, который работает с .ConfigureAwait(false)
, также работает, хотя и подмножественно, с .ConfigureAwait(true)
. Да, не весь код, но еще самый. Текущее значение по умолчанию позволяет работать с самым высоким процентом кода без использования настроек, которые, к сожалению, типичный программист не понимает.
Другое значение по умолчанию просто приведет к тысячам вопросов о том, почему код не работает, а еще хуже, тысячи ответов в форме "Microsoft отстой", они заставляют вас писать Control.CheckForIllegalCrossThreadCalls = false;
в каждой программе. Почему isn ' t что по умолчанию? " вместо фактического добавления соответствующих вызовов .ConfigureAwait(true)
.
Ответ 3
Посмотрите на второе примерное решение по этой ссылке:
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;
выполнял бы в потоке пула случайных потоков вместо потока пользовательского интерфейса.
Оба фрагмента выглядят как код, который может разумно написать, и по умолчанию один из них должен быть сломан. Так как взаимоблокировки намного менее опасны и проще обнаружить, чем небезопасные обращения, выбор ConfigureAwait(true)
по умолчанию является более консервативным выбором.