2016-10-21 3 views
0

В чем разница при использовании await в нескольких задачах ожидания и ожидании завершения всех задач. Моя позиция - это сценарий 2, который лучше с точки зрения производительности, поскольку одновременно выполняются как asyncTask1, так и asyncTask2.Разница между ожиданием Задача и ожидание Task.WhenAll

сценарий 1:

async Task Task() 
{ 
    await asyncTask1(); 
    await asyncTask2(); 
} 

сценарий 2:

async Task Task() 
{ 
    t1 = asyncTask1(); 
    t2 = asyncTask2(); 
    await Task.WhenAll(createWorkflowtask, getTaskWorkflowTask); 
} 
+1

Учитывая, что вы сами описали разницу, почему вы спрашиваете нас, в чем разница? Ты уже знаешь. – Servy

+0

@servry, я думал, что это сценарий, который приведет к лучшей производительности, но не уверен, что это охватывает все случаи кросс. или если есть сценарий, где для коротких задач. использование параллельного подхода - не самый лучший вариант. –

+3

Влияние на производительность будет зависеть от огромного количества вещей. Разница между двумя частями кода заключается в том, что первый выполняет операции последовательно, а второй - параллельно. – Servy

ответ

2

Вы писали: «... потому что оба asyncTask1 и asyncTask2 предварительно сформированы параллельно».

Нет, они не являются!

Дополнение: Ниже я написал, что все в async-wait выполняется одним потоком. Шнайдер правильно прокомментировал, что при асинхронном ожидании может быть задействовано несколько потоков.См. Дополнение в конце.

В статье, которая помогла мне много, чтобы понять, как асинхронному ждут работы был this interview with Eric-Lippert, который по сравнению асинхр/ждут с варочной делает ужин. (Где-то на полпути, найдите async-wait).

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

При использовании async/await все еще задействован один поток. Этот поток может делать только одно. Хотя поток занят Task1, он не может выполнить Task2. Только если он найдет ожидание в Task1, он начнет выполнение операторов из Task2. В вашем сценарии 2 задачи не выполняются параллельно.

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

Если вы действительно хотите, чтобы task2 что-то делал, а task1 тоже что-то делал, вам придется начать делать task2 в отдельном потоке. Самый простой способ сделать это в вашем случае будет:

var task1 = Task.Run(() => asyncTask1()) 
// this statement is executed while task1 begins executing on a different thread. 
// hence this thread is free to do other things, like performing statements 
// from task2: 
var task2 = asyncTask(); 
// the following statement will only be executed if task2 encounters an await 
DoSomethingElse(); 
// when we need results from both task1 and task2: 
await Task.WhenAll(new Task[] {task1, task2}); 

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

преимущество этого метода выше делать вещи параллельно являются многократно:

  • Все выполняется одним потоком: нет необходимости мьютексы, нет шансов тупика, голода и т.д.
  • Ваш код выглядит вполне последовательным. Сравните это с кодом, который использует Task.ContinueWith и подобные заявления
  • Там нет накладных расходов начать отдельный поток/погонный поток из пула потоков

Дополнения: комментарий Шнайдера ниже о нескольких нитях правильный.

Некоторые испытания показали, что идентификатор потока текущего потока в ожидаемых задачах отличается от идентификатора потока вызывающего потока.

Для новичков, ожидающих асинхронного ожидания, важно понимать, что хотя различные потоки задействованы, асинхронный ожидания НЕ означает, что задачи выполняются параллельно. Если вы хотите параллелизм, вы должны сказать, что задача должна выполняться параллельно.

Кажется, что повар в аналогии Эрика Липперта на самом деле является командой поваров, которые постоянно оглядываются, чтобы посмотреть, смогут ли они помочь некоторым другим поварам, а не ждать, пока их задачи закончатся. И действительно, если повар Альберт видит ожидания и начинает делать что-то еще, повар Бернард может закончить задачу повара Альберта.

+1

«При использовании async/await все еще есть один поток ...» - я думаю, что этот параграф вводит в заблуждение и/или путается. Во многих сценариях, вероятно, будет задействовано несколько потоков. То, что есть, является одним из логических потоков исполнения_, чтобы не путать с _one thread_. «Пока поток занят задачей Task1, он не может выполнить Task2». - это не причина, по которой Task2 не запускается одновременно с Task1 - это потому, что логический поток кода диктует это. Task2 запускается в невидимом продолжении, которое следует за Task1, возможно, запускается в другом потоке. – Schneider

6

В сценарии 1, задачи выполняются последовательно (asyncTask1 должны завершить до asyncTask2 начинается), тогда как в сценарии 2 две задачи могут выполняться в параллельны друг другу.

3

В первом сценарии вы запускаете задачу, а затем ждите, пока она не будет завершена, а затем перейдите ко второму и дождитесь окончания до выхода из метода.
Во втором сценарии запуска две задачи параллельно, а затем ждать, пока tgey не будут завершены, когда вы звоните Task.WhenAll

1

Использование Task.WhenAll

  • Вы не можете использовать методы с типами возврата если не все типы возвращаемых являются одинаковыми и используют общую версию метода WhenAll
  • У вас нет контроля над последовательностями, которые выполняются методами, поскольку эти методы выполняются параллельно
  • Необработанное исключение в одном методе не нарушает выполнение других методов (из параллельности)

От MSDN

Если какой-либо из поставленных задач завершается в поврежденном состоянии, возвращаемая задача также будет завершена в состоянии TaskStatus.Faulted, где его исключения будут содержать агрегацию набора разворачиваемых исключений из каждой из поставленных задач.

Использование await на нескольких методов

  • Вы контролируете последовательности, функции под названием

  • Вы можете использовать различные типы возврата и использования, что типы возвращаемых на следующих этапах

  • Необработанное исключение одним способом нарушит выполнение других методов

Смежные вопросы