Используют ли новые ключевые слова C# 5.0 "async" и "await" несколько ядер?
два новых ключевых слова, добавленные в язык C# 5.0 являются асинхронные и ждут, оба из которых работают рука об руку, чтобы запустить C# метод асинхронно, не блокируя вызывающий поток.
мой вопрос в том, действительно ли эти методы используют преимущества нескольких ядер и работают параллельно или асинхронный метод работает в том же ядре потока, что и вызывающий?
4 ответа:
две новые ключевые слова в язык C# 5.0 являются async и await, которые работают рука об руку, чтобы запустить C# метод асинхронно, не блокируя вызывающий поток.
это попадает через цель функции, но это дает слишком много "кредита" для функции async/await.
позвольте мне быть очень, очень ясным в этом вопросе:
awaitне вызывает волшебным образом синхронный метод для асинхронного выполнения. It например, не запускает новый поток и не запускает метод в новом потоке. Метод, который вы вызываете, должен быть тем, что знает, как запускать себя асинхронно. Как он решает это сделать-это его дело.мой вопрос в том, действительно ли эти методы используют преимущества нескольких ядер и работают параллельно или асинхронный метод работает в том же ядре потока, что и вызывающий?
опять же, это полностью зависит от метода, который вы звоните. Все это
awaitdoes-это указание компилятору переписать метод в делегат, который может быть передан как продолжение асинхронной задачи. То есть,await FooAsync()означает "вызовFooAsync()и все, что возвращается, должно быть чем-то, что представляет собой асинхронную операцию, которая только что началась. Скажите этой вещи, что когда она знает, что асинхронная операция выполнена, она должна вызвать этот делегат."Делегат имеет свойство, что при его вызове текущий метод кажется, чтобы возобновить "где он остановился".если метод, который вы вызываете расписания, работает на другом потоке, привязанном к другому ядру, отлично. Если он запускает таймер, который пингует некоторый обработчик событий в будущем в потоке пользовательского интерфейса, отлично.
awaitне волнует. Все, что он делает, это гарантирует, что когда асинхронное задание будет выполнено, управление может возобновиться там, где оно остановилось.вопрос, который вы не задавали, но, вероятно, должны были:
когда асинхронная задача закончено и управление поднимается там, где оно остановилось, выполняется в том же потоке, что и раньше?
это зависит от контекста. В приложении winforms, где вы ждете что-то из потока пользовательского интерфейса, элемент управления снова поднимается в потоке пользовательского интерфейса. В консольном приложении, возможно, нет.
у Эрика Липперта есть отличный ответ; я просто хотел описать
asyncпараллелизм немного дальше.просто "серийный" подход, где вы
awaitтолько одна вещь за раз:static void Process() { Thread.Sleep(100); // Do CPU work. } static async Task Test() { await Task.Run(Process); await Task.Run(Process); }в этом примере
Testметод будет стоять в очередиProcessв пул потоков, и когда он завершится, он будет стоять в очередиProcessснова в пул потоков. ЭлементTestспособ будет завершена после ~200мс. В любой момент времени только один поток двигается прогресс вперед.простой способ распараллелить это использовать
Task.WhenAll:static void Process() { Thread.Sleep(100); // Do CPU work. } static async Task Test() { // Start two background operations. Task task1 = Task.Run(Process); Task task2 = Task.Run(Process); // Wait for them both to complete. await Task.WhenAll(task1, task2); }в этом примере
Testочередей способProcessв пул потоков дважды, а затем ждет их обоих для завершения. ЭлементTestметод завершится через ~100 мс.
Task.WhenAll(иTask.WhenAny) были введены сasync/awaitдля поддержки простого параллелизма. Однако TPL все еще существует, если вам нужно что-то более продвинутое (истинная параллельная обработка с привязкой к процессору лучше подходит для TPL). TPL хорошо играет сasync/await.я покрываю основные
asyncпараллелизм в моем наasyncблоге, а также" контекст", на который ссылался Эрик.
асинхронный метод возвращает ожидаемый объект (тот, который имеет
GetAwaitermethod), и компилятор может генерировать код для использования этого объекта, если вы вызываете метод с помощьюawaitключевое слово. Вы также можете вызвать такой способ без ключевое слово await и явно использует объект.объект инкапсулирует асинхронное действие, которое может выполняться или не выполняться в другом потоке. Статья Эрика Липперта асинхронность в C# 5.0 Часть четвертая: это не магия рассматривается пример асинхронного программирования, который включает только один поток.