Почему Задача. Задержка не работает в этой ситуации

Я проверяю async , и я нашел эту ситуацию, что я не могу понять:

var watch = Stopwatch.StartNew();

var t1 = Task.Factory.StartNew(async() =>
{
    await Task.Delay(2000);

    return 2;
});

var t2 = Task.Factory.StartNew(() =>
{
    Task.Delay(1000);

    return 1; 
});

await Task.WhenAll(t1, t2);

var result = watch.ElapsedMilliseconds;

Я хотел бы понять, почему результат всегда 0! Почему не 1000, 2000 или сумма этих двух задач 3000? Почему не Задачу. WhenAll ждут завершения задач?

21
nl ja de
@GrantThomas I' m пытающийся назначить это на переменную, но это дает мне ошибку компилятора, как я могу сделать это?
добавлено автор MuriloKunze, источник
Я попробовал это: вар taskresult = ждет Задачи. WhenAll (t1, t2); Но это дает мне ' не Может назначить пустоту на неявно напечатанный местный variable'..
добавлено автор MuriloKunze, источник
@MuriloKunze, Чтобы ответить на тот вопрос we' d должен видеть линию кода и ошибки.
добавлено автор Servy, источник

1 ответы

Хорошо, таким образом, второй - легкий, поэтому давайте обращаться с тем.

Для второй задачи, t2 , вы ничего не делаете с результатом Задача. Задержка (1000) . Вы не <кодируете>, ждут это, вы не <кодируете>, Ждут это, и т.д. Учитывая, что метод не async , я предположил, что вы хотели для него быть блокированием, ждут. Чтобы сделать это, которое вы хотели бы добавить , Ждут() до конца , Задержка звонит, чтобы сделать его, блокирование ждет, или просто использует Нить. Сон() .


Для первой задачи вы кусаетесь тем, что вы используете вар . Более ясно, что происходит, когда вы не используете вар :

Task> t1 = Task.Factory.StartNew(async() =>
{
    await Task.Delay(2000);

    return 2;
});

Вы возвращаете задачу задачи интервал , не только Задача интервал . Внешняя задача "выполнена", как только внутренняя задача заканчивает начинаться. Когда вы используете WhenAll , вы не заботитесь о том, когда внешняя задача заканчивается, вы заботитесь о том, когда , внутренние задача, заканчиваются. Есть много способов обращаться с этим. Нужно использовать , Разворачивают .

Task t1 = Task.Factory.StartNew(async() =>
{
    await Task.Delay(2000);

    return 2;
}).Unwrap();

Now you have your expected Task and WhenAll will take at least 2000 milliseconds, as expected. You could also add in another await call to do the same thing:

Task t1 = await Task.Factory.StartNew(async() =>
{
    await Task.Delay(2000);

    return 2;
});

As mentioned by svick in a comment another option would be to just use Task.Run instead of StartNew. Task.Run has a special set of overloads for methods that take a Func> and return a Task and automatically unwrap them for you:

Task t1 = Task.Run(async() =>
{
    await Task.Delay(2000);

    return 2;
});

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


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

var t3 = Task.Delay(3000);
await Task.WhenAll(t1, t2, t3);

Если вы на самом деле просто хотите ждать установленной суммы времени, это - то, что необходимо делать.

42
добавлено
Большой ответ:)
добавлено автор MuriloKunze, источник
Есть другой выбор: используйте Задачу. Управляемый() . Это разворачивает задачу отдельно, таким образом, it' s, вероятно, лучший выбор, чем использование StartNew() объединенный с Разворачивают() .
добавлено автор svick, источник
@svick Правильный, хороший выбор, отредактированный в.
добавлено автор Servy, источник
+1 для большого ответа
добавлено автор Kamyar Nazeri, источник
Microsoft Stack Jobs
Microsoft Stack Jobs
1 788 участник(ов)

Work & freelance only Microsoft Stack. Feed https://t.me/Microsoftstackjobsfeed Чат про F#: @Fsharp_chat Чат про C#: @CSharpChat Чат про Xamarin: @xamarin_russia Чат общения:@dotnettalks

Microsoft Developer Community Chat
Microsoft Developer Community Chat
584 участник(ов)

Чат для разработчиков и системных администраторов Microsoft Developer Community. __________ Новостной канал: @msdevru __________ Баним за: оскорбления, мат, рекламу, флуд, флейм, спам, NSFW контент, а также большое количество оффтоп тем. @banofbot