ConfigureAwait (false) - всегда ли продолжение выполняется в другом потоке?

2

Этот вопрос задается в контексте 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. всегда выполняется в другом потоке? Или есть вероятность, что если поток, в который был захвачен контекст синхронизации, будет свободным после завершения асинхронной операции, то продолжение будет выполняться в том же потоке?

Теги:
async-await
asp.net-web-api

1 ответ

4
Лучший ответ

Когда меня спрашивают в отрицательной форме, ответ на этот вопрос, я думаю, довольно ясен - нет никакой гарантии, что вторая половина будет выполнена в потоке, отличном от первого. Как вы предполагаете, исходная нить вполне может быть удачной следующей доступной нитью, когда продолжение готово к выполнению.

Также важно отметить, что это контекст, а не обязательно поток, который восстанавливается. В случае цикла сообщений Windows (например, потока пользовательского интерфейса WinForms) именно поток пользовательского интерфейса, выполняющий цикл сообщений, получает и выполняет продолжение, следовательно, с ConfigureAwait(true) тот же поток гарантирован. Однако с другими объектами SynchronizationContexts не может быть особых причин требовать или даже предпочитать исходный поток, если все, что они считают "контекстом", восстанавливается; например, HttpContext.Current [, личность, культура] в ASP.NET.

Существует также, по крайней мере, теоретический шанс, что HeavyIo() завершится синхронно, в этом случае переключение контекста все равно не произойдет, и вторая половина просто продолжится в том же потоке, что и первая. Я могу только предположить из вашего выбора наименования ("тяжелый"), что вы намекаете, что это не вариант.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню