Разница между асинхронным и синхронным в .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.