AFAIK,
- Task , Task< TResult >обозначает обещание асинхронной операции.
- async await не блокирует вызывающий поток и не запускает асинхронный метод синхронно, но вызывающий поток освобождается с этого момента и, следовательно, взамен требуется обещание, заключающее его в Task или Task< TResult >, чтобы оно могло выполнить другую операцию. Преимущество здесь в том, что поток пользовательского интерфейса может выполнять другую работу.
- Контекст синхронизации — это оркестратор, который ведет учет потоков, которые необходимо вызвать для продолжения после завершения асинхронной операции, и он выполняет множество другие вещи . Я просто буду краток.
- ConfigureAwait(true) заставляет вызывающий поток ждать, пока асинхронная операция не завершится; false делает ее бесплатной
- Наконец во всех SO и других популярных блогах, которые async await не создают/не используют потоки пула потоков. Если быть точным, потоки не задействованы.
Код: Выделить всё
public class ValuesController : ApiController
{
// GET api/values
public async Task Get()
{
Debug.WriteLine($"Controller : {Thread.CurrentThread.ManagedThreadId} ThreadId");
var res = await SomeAsyncOperation().ConfigureAwait(true);
Debug.WriteLine($"Controller : {Thread.CurrentThread.ManagedThreadId} ThreadId");
return res;
}
private async Task SomeAsyncOperation()
{
Debug.WriteLine($"SomeAsyncOperation 1: {Thread.CurrentThread.ManagedThreadId} ThreadId");
var re = await SomeOther2AsyncOp().ConfigureAwait(true);
Debug.WriteLine($"SomeAsyncOperation 2: {Thread.CurrentThread.ManagedThreadId} ThreadId");
await Task.Delay(1000).ConfigureAwait(true);
Debug.WriteLine($"SomeAsyncOperation 3: {Thread.CurrentThread.ManagedThreadId} ThreadId");
return re.ToString().ToLower();
}
private async Task SomeOther2AsyncOp()
{
Debug.WriteLine($"SomeAsyncOperation2 1: {Thread.CurrentThread.ManagedThreadId} ThreadId");
await Task.Delay(1000).ConfigureAwait(true);
Debug.WriteLine($"SomeAsyncOperation2 2: {Thread.CurrentThread.ManagedThreadId} ThreadId");
return "Hello";
}
}
Код: Выделить всё
Controller : 11 ThreadId
SomeAsyncOperation 1: 11 ThreadId
SomeAsyncOperation2 1: 11 ThreadId
SomeAsyncOperation2 2: 12 ThreadId
SomeAsyncOperation 2: 12 ThreadId
SomeAsyncOperation 3: 12 ThreadId
Controller : 12 ThreadId
Несколько вопросов
- Использование потоков ThreadPool имеет смысл потому что какой-то работник должен вернуть значение из асинхронной операции, как только ожидание получит результат. Тогда почему все говорят «Нет потоков»?
- Я использовал ConfigurationAwait(true) Тогда я предполагал это будет использовать тот же поток, который запустил контекст запроса, чтобы завершить запрос и отправить ответ обратно. Но здесь не тот случай. ПОЧЕМУ?
- Почему первое переключение контекста происходит в SomeOther2AsyncOp(), а не в SomeAsyncOperation(), потому что async await создает конечный автомат из двух частей: одну до await и другую после await. Достаточно ли компилятор умен, чтобы проверить кодовую базу и настроенный конечный автомат?
- Aspnet Core не имеет контекста синхронизации, поэтому означает ли это, что все операции асинхронного ожидания будут использовать потоки пула потоков, т.е. 1 контекст переключаться для каждого метода? В этом случае производительность улучшается, потому что один запрос будет потреблять много фоновых потоков.
- Если я объявлю асинхронность таким образом, например, делегируя единицу работы какому-то работнику и получая уведомление, когда рабочий работа выполнена, это звучит правильно?
Подробнее здесь: https://stackoverflow.com/questions/781 ... ts-written