разница между асинхронным и синхронным in.net 4.5

во время моего чтения об асинхронном программировании в .Net 4.5 async и await ключевые слова Я читаю здесь следующий пункт

Обработка Асинхронных Запросов

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

для смелых слов я не мог понять, как асинхронный запрос занимает столько же времени для обработки, сколько синхронный запрос?

например:

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(); чтобы выполнить его?

если да Итак, в чем разница между асинхронным программированием и многопоточностью Программирование ?

обновление:

предположим, что код становится таким:

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() казнь?

3 ответов


асинхронные операции не быстрее. Если вы ждете 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 (как и другие по-настоящему асинхронные операции) не требует выполнения потока и поэтому there is no thread. Task.Delay реализуется с помощью System.Threading.Timer что вы запускаете, и он вызывает событие, когда это сделано, в то же время ему не нужен поток, потому что нет кода для выполнения.

Итак, когда поток, который работал MyMethod достигает await longRunningTask он освободился (как пока longRunningTask еще не завершена). Если бы это был ThreadPool поток он вернется к ThreadPool где он может обрабатывать другой код в вашем приложении.


что касается обновления, поток будет таким:

  • MyMethod начинается обработка
  • LongRunningOperation начинается обработка
  • DoSomeWorkNeedsExecution выполняется в вызывающем потоке
  • Теги await находится в LongRunningOperation и поэтому горячая задача возвращенный.
  • DoIndependentWork выполняется тем же вызывающим потоком (LongRunningOperation по-прежнему "работает" , поток не требуется)
  • Теги await находится в MyMethod. Если исходная задача завершена, тот же поток будет продолжаться синхронно, если нет, то будет возвращена горячая задача, которая в конечном итоге завершится.

поэтому тот факт, что вы используете async-await позволяет использовать поток, который в противном случае будет заблокирован, ожидая синхронного выполнения CPU-интенсивная работа.


рассмотрим разницу между:

Thread.Sleep(1000);

и

await Task.Delay(1000);

обоим потребуется одна секунда для запуска. Однако в первом случае текущий поток будет заблокирован (и все его ресурсы бесполезны), а во втором случае текущий поток может сделать что-то еще, что полезно (например. обслуживание другого запроса).

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

Re. еще вопрос

освобожденный поток(ы) будет использоваться для других вещей; до завершения операции не будет назначен поток. Это возможно, потому что базовая ОС сама по себе асинхронна. В приведенном выше примере используется таймер, который сигнализирует потоку, чтобы забрать, когда поток свободен, а не поток, остановленный для внутреннего.


(основываясь на ответе И3арнона)

это не совсем правда, что синхронные операции и операции с использованием async-await будет, в целом, займет то же время.

есть некоторая дополнительная логика, связанная с async-await. Проверки выполненных awaiters и государственной машины. Это заставляет некоторые асинхронные операции занимать больше времени, чем соответствующая синхронная операция.

С другой стороны, большинство операций подходит для async-await естественно асинхронный и есть некоторая дополнительная обработка, чтобы сделать его выглядеть и чувствовать себя синхронным. В этих случаях асинхронная операция занимает меньше времени, чем синхронный аналог.

цитата по вопросу связана с веб-приложениями. Для веб-приложений асинхронные операции-это скорее обслуживание максимального количества запросов за приемлемое время, чем сохранение нескольких микросекунд каждого запроса. С другой стороны, если задействовано переключение контекста, это в конечном итоге занимает больше времени, и именно поэтому использование Task.Run в веб-приложение делает больше плохого, чем хорошего применения.

если вы хотите узнать больше о async-awit читаем статьи о мой async-awit курирование.