好的,所以,第二个是简单的,所以让我们来处理那个。
对于第二项任务t2
,您不会对Task.Delay(1000)
的结果做任何事情。你不是await
它,你不是Wait
它等等。鉴于方法不是async
我想你的意思是它是一个阻塞等待。要做到这一点,您希望将Wait()
添加到Delay
调用的末尾,以使其成为阻止等待,或者仅使用Thread.Sleep()
。
对于第一个任务,你被一个事实,即你使用var
咬伤。这是更清晰的发生了什么,当你不使用var
:
Task<Task<int>> t1 = Task.Factory.StartNew(async() =>
{
await Task.Delay(2000);
return 2;
});
你回不只是int
的Task
的int
任务的任务。内部任务完成后,外部任务将“完成”。当您使用WhenAll
时,您不关心外部任务何时完成,您关心何时完成任务内部任务完成。有很多方法可以解决这个问题。一种是使用Unwrap
。
Task<int> t1 = Task.Factory.StartNew(async() =>
{
await Task.Delay(2000);
return 2;
}).Unwrap();
现在,你有你的预期Task<int>
和WhenAll
将需要至少2000毫秒,符合市场预期。你也可以添加在另一个await
调用做同样的事情:
Task<int> t1 = await Task.Factory.StartNew(async() =>
{
await Task.Delay(2000);
return 2;
});
正如svick in a comment提到的另一种选择是只用Task.Run
,而不是StartNew
。 Task.Run
具有该采取Func<Task<T>>
并返回Task<T>
,并自动解开他们为你的方法一组特殊的重载:
Task<int> t1 = Task.Run(async() =>
{
await Task.Delay(2000);
return 2;
});
出于这个原因,它是最好使用Task.Run
为默认选项,当你创建异步lambda表达式因为它会为您“处理”这个问题,但最好在无法使用Task.Run
的复杂案例中了解它。
最后我们来看看你没有做的选择,这是你在这种情况下应该实际做的。由于Task.Delay
已经返回一个任务,因此无需首先将其放入StartNew
。而不是创建一个嵌套的任务和使用Unwrap
你只是没有在第一时间把它包:
var t3 = Task.Delay(3000);
await Task.WhenAll(t1, t2, t3);
如果你真的只是想等待这是你应该做的事情的固定时间量。
@GrantThomas我想分配给一个变量,但它给了我一个编译器错误,我该怎么做? – MuriloKunze
@MuriloKunze为了回答这个问题,我们需要看到代码行和错误。 – Servy
我试过这个:var taskresult = await Task.WhenAll(t1,t2); 但它给了我一个'不能分配void的隐式类型局部变量'。 – MuriloKunze