Страницы

Поиск по вопросам

понедельник, 25 февраля 2019 г.

await + ConfigureAwait()

Коллеги, добрый день. Прошу помощи с ConfigureAwait().
Мои знания на таком уровне: это метод, который указывает среде выполнения, что при возвращении из асинхронного метода (запущенного в другом потоке) не нужно пользоваться контекстом синхронизации. Т.е. не ждать пока освободится поток, в котором началось выполнение кода (до await), а продолжать выполнение кода (который после await) в том же потоке, в каком выполнялся сам асинхронный таск (сам await). Это повышает производительность, однако стоит использовать с осторожностью в задачах где присутствуют UI потоки (WPF, ASP.NET). Поправьте пожалуйста, если я не прав.
И дальше возникает второй вопрос. Допустим у меня есть такая цепочка асинхронных вызовов:
public async Task M1() { return await M2(); }
public async Task M2() { return await M3(); }
public async Task M3() { return await dbContext.Users .ToListAsync() .ConfigureAwait(false); }
В методе M3() происходит асинхронное ожидание. EF создает новый поток и читает из БД, мы ждем. Все ок.
А что происходит в M2()? Создается ли новый поток для выполнения таска await M3(). Аналогичный вопрос для метода M1(). Стоит ли в этих await-ах использовать ConfigureAwait(false), либо достаточно того, что мы использовали этот метод в M3()?


Ответ

Смотрите.
ConfigureAwait(false) действует напрямую только на await, который ожидает данный Task (точнее, данный tasklike). Это означает, что во внешней функции будет обычным образом захвачен контекст, и выполнение вернётся туда по окончанию await. То, в каком или в каких контекстах пробегает код M1, не играет роли, если M2 бежит в синхронизационном контексте.

Комментариев нет:

Отправить комментарий