Требуется ли Wait () после использования Task.Factory.StartNew ()? - PullRequest
9 голосов
/ 12 января 2011

Практически вся документация, которую я видел по использованию C # 4.0 Task.Factory.StartNew, гласит, что для ожидания завершения Задачи вам нужно Wait. Но мое первоначальное тестирование показывает, что это не нужно. Кто-нибудь еще может дать мне подтверждение по этому поводу? Мне любопытно, почему так много онлайн и печатных ссылок говорят, что вы должны позвонить подождать.

Вот простое консольное приложение, которое показывает, что мне не нужен оператор Wait, поэтому я закомментировал его. Независимо от того, комментирую я tsk.Wait () или нет, вывод одинаковый.

Ожидаемый результат во всех случаях следующий:

Main thread starting.
After running MyTask. The result is True
After running SumIt. The result is 1
Main thread ending.

код:

class Program
{
    // A trivial method that returns a result and takes no arguments.
    static bool MyTask()
    {
        Thread.Sleep(2000);
        return true;
    }

    // This method returns the summation of a positive integer
    // which is passed to it.
    static int SumIt(object v)
    {
        int x = (int)v;
        int sum = 0;
        for (; x > 0; x--)
            sum += x;
        return sum;
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Main thread starting.");
        // Construct the first task.
        Task<bool> tsk = Task<bool>.Factory.StartNew(() => MyTask());
        // I found this Wait statement to be completely unnecessary.
        //tsk.Wait();
        Console.WriteLine("After running MyTask. The result is " +
        tsk.Result);
        // Construct the second task.
        Task<int> tsk2 = Task<int>.Factory.StartNew(() => SumIt(1));
        Console.WriteLine("After running SumIt. The result is " +
        tsk2.Result);
        tsk.Dispose();
        tsk2.Dispose();
        Console.WriteLine("Main thread ending.");
        Console.ReadLine();
    }
}

Ответы [ 4 ]

19 голосов
/ 12 января 2011

Если вы просто хотите подождать, пока задача завершится, рекомендуемый порядок действий - позвонить .Wait(). Для Task (в отличие от Task<T>) это единственный вариант.

Для Task<T>, однако, есть также .Result, который также ждет, и это то, что вы используете. Так что в вашем случае нет необходимости звонить .Wait().

2 голосов
/ 12 января 2011

Одна важная особенность Wait заключается в том, что она действует как точка рандеву, так как любое исключение, выброшенное Task, будет повторно выброшено в этой точке. Поскольку текущая Task реализация * заставляет вас наблюдать любое такое исключение, Wait является хорошим вариантом для этого. Однако вы также можете наблюдать исключение, запросив экземпляр Task для исключения.

*) Видимо, это будет изменено. Поведение изменяется в Async CTP.

1 голос
/ 12 января 2011

Как заявил Тимви, результат тоже ждет.Так как вы используете tsk.Result в своем вызове Console.WriteLine, вы делаете ожидание как побочный эффект.

Это также зависит от того, сколько времени занимает выполнение задачи.Если оно очень короткое, вы можете не осознавать необходимость .Wait, потому что, кажется, оно всегда заканчивается вовремя.Существует опасность в том, что вы можете пропустить это, если вам нужно выполнить задачу, прежде чем продолжить.Поэтому .Wait следует использовать, даже если в 99% случаев он фактически не тратит время на ожидание.

1 голос
/ 12 января 2011

Так как согласно this , доступ к Value из Task гарантирует, что задача выполнена, вы правы, что она не требуется.

...