2017-02-07 7 views
-1

Я смущен этим кодом. В соответствии с документацией, которая включает этот код, , он вызывает каждую задачу, которая позволяет им выполнять одновременно, а затем ожидает, что они будут завершены.Как выполнить несколько задач async одновременно

Я не понимаю, как работает порядок выполнения. Объявив задачу var firstTask = DoSomethingAsync();, это заставляет задачу начать выполнение? Я думал, что это синхронно без выражения ожидания.

public async Task RunConcurrentTasks() 
{ 
    var firstTask = DoSomethingAsync(); 
    var secondTask = DoSomethingElseAsync(); 

    await firstTask; 
    await secondTask; 
} 

Также этот код достигает того же результата?

public async Task RunConcurrentTasks() 
{ 
    var firstTask = DoSomethingAsync(); 
    var secondTask = DoSomethingElseAsync(); 

    await Task.WhenAll(firstTask, secondTask); 
} 
+0

@Igor так что этот код: 'вар firstTask = DoSomethingAsync(); var secondTask = DoSomethingElseAsync(); 'вызывает вызов каждой задачи и начало ее выполнения? Как бы я сделал это синхронно, если бы захотел? –

+0

Если у вас есть новый вопрос «как запустить синхронный метод асинхронизации», пожалуйста, задайте его как вопрос (очевидно, все стандартные требования применяются). Невозможно понизить комментарий из-за отсутствия исследований ... –

ответ

0

при вызове метода асинхронного, с parenthesys (), такие как DoSomethingAsync(); начнет выполнение функциональных возможностей асинхронного. Он немедленно вернет Task, в котором содержится информация о выполняемых асинхронных функциях и дается системе знать, когда она будет закончена.

Чтобы запустить их по порядку, просто ждите каждого отдельно, а не ожидайте вызова WhenAll. Таким образом:

public async Task RunConcurrentTasks() 
{ 
    await DoSomethingAsync(); 
    await DoSomethingElseAsync(); 
} 

Теперь DoSomethingElseAsync будет ждать вызова DoSomethingAsync перед выполнением.

+0

Почему вы поставили такую ​​опасную рекомендацию использовать '.Result' в ответе, когда его даже не задали в вопросе? –

+0

Ну, он задал вопрос о том, как выполнить задачу синхронно. В своем комментарии. – maksymiuk

+0

OP должен был задавать отдельный вопрос (действительно должен был искать ответ сами), есть много дискуссий по теме на SO). На самом деле нет веских оснований просто упомянуть '.Result' без надлежащих ссылок на проблемы, вызываемые этим вызовом. Было бы гораздо лучше ответить на комментарий (или сначала отредактировать комментарий в вопросе, но это будет слишком широко распространенным вопросом). –

1

Объявление задачи var firstTask = DoSomethingAsync(); это заставляет задачу начать выполнение?

Да.

Как выполнить выполнение на следующей строке для вызова второй задачи?

Он будет работать DoSomethingAsync, пока он не достигнет своего первого await, который дает. В этот момент DoSomethingAsync возвращает задание, которое еще не завершено, а вызывающий абонент RunConcurrentTasks продолжает следующую строку.

Я думал, что это синхронно без выражения ожидания.

Нет, это все еще асинхронно. await не пробег все. await приведет к тому, что потребительский код будет асинхронно ждать («ожидание») для задачи до завершено.

Возможно, вы найдете мой async intro.

6

var firstTask = DoSomethingAsync(); Заставляет ли это выполнение задачи?

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

Как выполнить выполнение на следующей строке для вызова второй задачи?

Непонятный вопрос.

Я думал, что это синхронно без выражения ожидания.

Ваши убеждения неверны. «Ожидание» не означает «сделать это асинхронным». Не ждать создания и уничтожения асинхронности; он просто управляет существующей асинхронностью. DoSomethingAsync is уже асинхронный независимо от любого await. Опять же, говорит, что он делает что-то асинхронно, так что лучше быть тем, чем он занимается!

await в вашем примере всего return. Это означает «вернуться к моему абоненту и снова запустить этот метод в будущем после того, как ожидаемая задача будет завершена». Это асинхронное ожидание .

Подумайте, await как быть yield return. Когда вы находитесь в блоке итератора, и вы сталкиваетесь с возвратом доходности, метод возвращается, а затем он забирает место, где он остановился в какой-то момент в будущем. await в основном то же самое; только механизмы немного отличаются.

Еще один способ подумать, что await отмечает точку, где текущий метод не может продолжаться до тех пор, пока ожидаемая задача не будет завершена.. Поскольку метод не может продолжать работать, он возвращается.

Снова, await ничего не делает позвонил по правой стороне. Это просто оператор, и он подчиняется всем обычным правилам операторов:

await Foo(); 

и

var blah = Foo(); 
await blah; 

одно и то же, так же, как

var x = Foo() + Bar(); 

и

var f = Foo(); 
var b = Bar(); 
var x = f + b; 

- это то же самое. Ожидание не делает что-то магическое для его операндов, не более + делает что-то волшебное для своих операндов. Это просто особый вид возвращения.

Кроме того, делает ли этот код то же самое?

Пожалуйста, не задавайте два вопроса в одном вопросе. Отправьте два вопроса, если у вас есть два вопроса.

Вопрос неясен. Семантика обоих рабочих процессов заключается в том, что задача, возвращаемая RunConcurrentTasks, сигнализируется как завершаемая, когда выполняются все дочерние задачи, если это то, о чем вы просите.

+1

Ваше утверждение «Думайте, что вы ожидаете возвращения к доходности», действительно разъяснили async/ждут меня. – OldFart

+0

@OldFart: вы можете думать о 'IEnumerable ', 'IObservable ', 'Func ' и 'Task ', поскольку все это одно и то же с незначительными вариациями. Последовательность «предоставляет следующее значение, когда я спрашиваю». Наблюдаемое значение «дает следующее значение, когда оно доступно». Функция «предоставляет одно значение, когда я спрашиваю». Задача «предоставить одно значение, когда оно доступно».То же самое; все, что отличается, - это (1), сколько значений предоставлено, и (2) ли вы * вытягиваете * значение или его * толкаете * у вас. –

+0

@Eric Благодарим вас за этот комментарий о 'IEnumerable ', 'IObservable ', 'Func ' и 'Task '. Ваше объяснение помогает унифицировать отношения между типами. –

0

Task Documentation

Класс Task представляет собой одну операцию, которая не возвращает значение, и, как правило, выполняет асинхронно. Объекты задачи являются одним из центральных компонентов асинхронного шаблона на основе задач, впервые представленного в .NET Framework 4. Поскольку работа, выполняемая объектом Task, обычно выполняется асинхронно в потоке пула потоков, а не синхронно в основной прикладной нити. .

Вот ваш код, аннотированный, надеюсь, это имеет смысл.

public async Task RunConcurrentTasks() 
{ 
    // starts DoSomethingAsync and returns a Task which contains the information about the running state of that operation 
    // the thread that called this gets that Task as a result immediatly and can continue on to the next statement while this is running 
    var firstTask = DoSomethingAsync(); 

    // starts DoSomethingElseAsync and returns a Task which contains the information about the running state of that operation 
    // the thread that called this gets that Task as a result immediatly and can continue on to the next statement while this is running 
    var secondTask = DoSomethingElseAsync(); 

    // suspend the execution of the method until the awaited task completes 
    // only then do we proceed to the next line (assuming no exception was thrown) 
    await firstTask; 

    // suspend the execution of the method until the awaited task completes 
    // only then do we proceed to the next line (assuming no exception was thrown) 
    await secondTask; 
} 


public async Task RunConcurrentTasks() 
{ 
    // starts DoSomethingAsync and returns a Task which contains the information about the running state of that operation 
    // the thread that called this gets that Task as a result immediatly and can continue on to the next statement while this is running 
    var firstTask = DoSomethingAsync(); 

    // starts DoSomethingElseAsync and returns a Task which contains the information about the running state of that operation 
    // the thread that called this gets that Task as a result immediatly and can continue on to the next statement while this is running 
    var secondTask = DoSomethingElseAsync(); 

    // suspend the execution of the method until the awaited DoSomethingAsync AND DoSomethingElseAsync have completed 
    // only then do we proceed to the next line (assuming no Exceptions was thrown) 
    await Task.WhenAll(firstTask, secondTask); 
} 

Из комментариев

Как бы я это делать синхронно, если бы я хотел?

Await documentation

Оператор Await применяются к задаче в асинхронном методе, чтобы приостановить исполнение метода, пока ожидаемая задача не завершит

Использования await сразу после каждого вызова, это гарантирует, что выполнение не переходит к следующей строке до тех пор, пока результат (или исключение) не будет возвращен из выполнения ожидающей задачи. Это фактически не делает его синхронным в техническом смысле слова. Итак, сделайте свой первый пример и измените порядок строк, чтобы вы вызвали await после начала первой операции и перед началом 2-й операции.

var firstTask = DoSomethingAsync(); 
await firstTask; 
var secondTask = DoSomethingElseAsync(); 
await secondTask; 

, который также может быть переписано в виде

await DoSomethingAsync(); 
await DoSomethingElseAsync(); 
+0

Мы делаем ** NOT ** "прекратить выполнение этой темы". Вся * точка * 'await' заключается в том, чтобы ** избегать ** прекращения выполнения в потоке! –

+0

@EricLippert - плохая формулировка с моей стороны, я перефразировал (также формулировку в комментариях кода). – Igor

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

  • Нет связанных вопросов^_^