好的,所以,第二个是简单的,所以让我们处理那个。
对于第二个任务 ,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;
});
您正在返回一个 task of 的任务int
,而不仅仅是一个Task
of 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在评论中提到的那样,另一种选择是只使用Task.Run
而不是StartNew
. 对于接受 a并返回 a并自动为您解包它们的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);
如果您实际上只想等待固定的时间,那您应该这样做。