Этот вопрос задается в контексте ASP.NET WebApi 2 (не ASP.NET Core). Я попытался провести собственное исследование по этой теме, однако не смог найти однозначного ответа на этот вопрос.
Официальная документация MSDN для параметра метода ConfigureAwait(...)
гласит следующее:
true
попытка маршалинга продолжения обратно в исходный захваченный контекст; иначеfalse
.
Стивен Тауб далее объясняет ключевое слово attempt
следующим образом:
Это означает, что не может быть чего-то, что нужно маршалировать обратно... может не быть контекста для захвата, например,
SynchronizationContext.Current
может возвращатьnull
.
Если я правильно понимаю, то это не относится к ASP.NET WebApi 2, потому что присутствует AspNetSynchronizationContext
, верно?
Теперь давайте посмотрим на следующий метод действия контроллера:
[HttpGet]
public async Task<String> GetValues()
{
// First half.
var values = await HeavyIo().ConfigureAwait(false);
// Second half.
return values;
}
Передавая continueOnCapturedContext: false
гарантируется, что продолжение помечено как //Second half.
всегда выполняется в другом потоке? Или есть вероятность, что если поток, в который был захвачен контекст синхронизации, будет свободным после завершения асинхронной операции, то продолжение будет выполняться в том же потоке?
Когда меня спрашивают в отрицательной форме, ответ на этот вопрос, я думаю, довольно ясен - нет никакой гарантии, что вторая половина будет выполнена в потоке, отличном от первого. Как вы предполагаете, исходная нить вполне может быть удачной следующей доступной нитью, когда продолжение готово к выполнению.
Также важно отметить, что это контекст, а не обязательно поток, который восстанавливается. В случае цикла сообщений Windows (например, потока пользовательского интерфейса WinForms) именно поток пользовательского интерфейса, выполняющий цикл сообщений, получает и выполняет продолжение, следовательно, с ConfigureAwait(true)
тот же поток гарантирован. Однако с другими объектами SynchronizationContexts не может быть особых причин требовать или даже предпочитать исходный поток, если все, что они считают "контекстом", восстанавливается; например, HttpContext.Current
[, личность, культура] в ASP.NET.
Существует также, по крайней мере, теоретический шанс, что HeavyIo()
завершится синхронно, в этом случае переключение контекста все равно не произойдет, и вторая половина просто продолжится в том же потоке, что и первая. Я могу только предположить из вашего выбора наименования ("тяжелый"), что вы намекаете, что это не вариант.