Разница между асинхронным и синхронным в .net 4.5
Во время моего чтения о асинхронном программировании в ключевых словах .Net 4.5 async
и await
Я прочитал здесь в следующем абзаце
Обработка асинхронных запросов
В веб-приложениях, которые видят большое количество одновременных запросов в пуск или имеет взрывную нагрузку (где concurrency внезапно увеличивается), асинхронность этих веб-сервисов приведет к увеличению отзывчивость вашего приложения. Выполняется асинхронный запрос такое же количество времени для обработки как синхронный запрос. Для Например, если запрос вызывает вызов веб-службы, который требует двух секунд для завершения, запрос занимает две секунды, независимо от того, выполняется синхронно или асинхронно. Однако во время асинхронный вызов, поток не блокируется от ответа на другой когда он ждет завершения первого запроса. Следовательно, асинхронные запросы предотвращают очередь запросов и рост пула потоков когда есть много параллельных запросов, которые вызывают длительный операции.
для жирных слов, я не мог понять их, как асинхронный запрос занимает столько же времени, сколько и для синхронного запроса?
Например:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
await Task.Delay(1000); //1 seconds delay
return 1;
}
Что я понимаю, что LongRunningOperation()
запускает выполнение из первой строки, вызывающей здесь Task<int> longRunningTask = LongRunningOperation();
, и возвращает значение после вызова await
,
поэтому, с моей точки зрения, асинхронный код быстрее, чем синхронный, верно?
Другой вопрос:
Я понимаю, что основной поток, работающий над выполнением MyMethod()
не заблокирован, ожидая выполнения LongRunningOperation()
, чтобы выполнить, но он возвращается в пул потоков, чтобы обслуживать другой запрос. так есть ли другой поток, назначенный LongRunningOperation();
для его выполнения?
Если да, то в чем разница между асинхронным программированием и программированием многопоточности?
Update:
скажем, что код становится таким:
public async Task MyMethod()
{
Task<int> longRunningTask = LongRunningOperation();
//indeed you can do independent to the int result work here
DoIndependentWork();
//and now we call await on the task
int result = await longRunningTask;
//use the result
Console.WriteLine(result);
}
public async Task<int> LongRunningOperation() // assume we return an int from this long running operation
{
DoSomeWorkNeedsExecution();
await Task.Delay(1000); //1 seconds delay
return 1;
}
В этом случае будет выполняться LongRunningOperation()
другим потоком во время выполнения DoIndependentWork()
?
Ответы
Ответ 1
Асинхронные операции выполняются не быстрее. Если вы ждете в течение 10 секунд асинхронно (т.е. await Task.Delay(10000)
) или синхронно (т.е. Thread.Sleep(10000)
) , это займет те же 10 секунд. Единственное различие заключалось бы в том, что сначала не будет удерживать поток во время ожидания, а второй будет.
Теперь, если вы запускаете задачу и не ждете ее завершения, вы можете использовать тот же поток для выполнения какой-либо другой работы, но не ускоряете асинхронный запуск:
var task = Task.Delay(10000);
// processing
await task; // will complete only after 10 seconds
О вашем втором вопросе: Task.Delay
(как и другие по-настоящему асинхронные операции) не нужен поток для выполнения, поэтому нет нити. Task.Delay
реализуется с помощью System.Threading.Timer
, который вы запускаете, и он вызывает событие, когда это делается, тем временем ему не нужен поток, потому что нет кода для выполнения.
Итак, когда поток, который работал MyMethod
, достигает await longRunningTask
, он освобождается (пока longRunningTask
еще не завершен). Если это был поток ThreadPool
, он вернется к ThreadPool
, где он сможет обработать некоторый другой код в вашем приложении.
Что касается обновления, поток будет таким:
-
MyMethod
начинает обработку
-
LongRunningOperation
начинает обработку
-
DoSomeWorkNeedsExecution
выполняется в вызывающем потоке
- В
LongRunningOperation
достигается await
, и поэтому возвращается горячая задача.
-
DoIndependentWork
выполняется одним и тем же вызывающим потоком (LongRunningOperation
по-прежнему "работает", нить не требуется)
- А
await
достигается в MyMethod
. Если исходная задача выполнена, тот же поток будет продолжаться синхронно, если нет, тогда будет возвращена горячая задача, которая в конечном итоге завершится.
Таким образом, тот факт, что вы используете async-await
, позволяет использовать поток, который в противном случае был бы заблокирован, ожидая синхронно, чтобы выполнить интенсивную работу с ЦП.
Ответ 2
Рассмотрим разницу между:
Thread.Sleep(1000);
и
await Task.Delay(1000);
для запуска потребуется одна секунда. Однако в первом случае текущий поток будет заблокирован (и все его ресурсы бесполезны), а в последнем случае текущий поток может сделать что-то еще полезное (например, обслуживающий другой запрос).
Асинхронность не в ускорении отдельных последовательностей инструкций, а в том, что они могут делать то, что блокирует синхронный код.
Re. Другой вопрос
Вырезанные нити будут использоваться для других вещей; до завершения операции не будет назначена нить. Это возможно, потому что базовая ОС сама по себе асинхронна. В приведенном выше примере используется таймер, который сигнализируется о том, что поток будет забираться, когда поток свободен, а не поток, остановленный для внутреннего.
Ответ 3
(исходя из ответа I3arnon)
Не совсем верно, что синхронные операции и операции с использованием async-await
будут, в общем, занять одно и то же время.
В async-await
есть дополнительная логика. Проверяются завершенные ожидания и конечный автомат. Это приводит к тому, что некоторые асинхронные операции занимают больше времени, чем соответствующая синхронная операция.
С другой стороны, большинство операций, подходящих для async-await
, естественно асинхронны, и есть некоторая дополнительная обработка, чтобы заставить ее выглядеть и чувствовать синхронность. В этих случаях асинхронная операция занимает меньше времени, чем синхронная копия.
Цитата о вопросе связана с веб-приложениями. Для веб-приложений асинхронные операции больше касаются обслуживания максимального количества запросов в приемлемое время, чем сохранение нескольких микросекунд каждого запроса. С другой стороны, если задействование контекста задействовано, оно заканчивается тем, что занимает больше времени, и почему использование Task.Run
в веб-приложении делает приложение более вредоносным.
Если вы хотите узнать больше о async-awit
, прочитайте статьи my async-awit
curation.