Await Task.WhenAll() внутри задачи, не ожидающей

Моя проблема заключается в том, что когда задача имеет вызов Task.WhenAll() (запуская другие задачи), строка WhenAll() заставляет потребляющий код продолжать выполнение, в отличие от того, что я ожидал. Таким образом, следующий код выводит "finished" сразу после нажатия Task.WhenAll(), а не после завершения всех задач в его аргументе.

    // Just a simple async method
    public Task DoWorkAsync()
    {
        return Task.Factory.StartNew(
            () =>
            {
                // Working
            });
    }

    // This one used the previous one with Task.WhenAll()
    public Task DoLoadsOfWorkAsync()
    {
        return Task.Factory.StartNew(
            async () =>
            {
                // Working
                // This line makes the task return immediately
                await Task.WhenAll(DoWorkAsync(), DoWorkAsync());
                // Working
            });
    }

    // Consuming code
    await DoLoadsOfWorkAsync();
    Console.WriteLine("finished");

Я ожидаю, что WriteLine() будет вызываться при выполнении последней строки DoLoadsOfWorkAsync().

Что я делаю не так? Заранее спасибо.


person Piedone    schedule 17.11.2012    source источник


Ответы (1)


Task.WhenAll возвращает новый Task сразу, не блокирует. Возвращенная задача будет завершена, когда все задачи, переданные WhenAll, будут завершены.

Это асинхронный эквивалент Task.WaitAll. , и это метод, который следует использовать, если вы хотите заблокировать.

Однако у вас есть другая проблема. Использование Task.Factory.StartNew и передача делегата async похоже, приводит к типу Task<Task>, где внешняя задача завершается, когда начинает выполняться внутренняя задача (а не когда она завершена).

Этого можно избежать с помощью более нового Task.Run.

person Richard    schedule 17.11.2012
comment
Вы прибили это: проблема была в Задаче‹Задание›, я ее проглядел. Кстати, я не хочу, чтобы поток блокировался, просто чтобы продолжить выполнение после завершения предыдущих задач. Вот почему я использовал Task.WhenAll() вместо ожидания вместе с конструкцией aync-await. Большое спасибо за Вашу помощь! - person Piedone; 17.11.2012
comment
если вы хотите прочитать о Task.Run и обо всех его достоинствах (а также о том, почему и как он делает то, что он делает), перейдите сюда: blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx - person ckozl; 05.04.2013