委托中Task.Delay之后的代码未执行 [英] Code after Task.Delay in delegate not executing
问题描述
我正在尝试同时处理列表的分区.对于列表中每个分区中的每个整数,我都在等待那段时间.
I am trying to concurrently process partitions of a list. For each integer in each partition of the list I am trying to wait for that amount of time.
public class Program
{
public async static void Main()
{
Console.WriteLine("Starting.");
var values = Enumerable.Range(0,1000).ToList();
await Task.WhenAll(
from partition in Partitioner.Create(values).GetPartitions(10)
select Task.Run(async delegate {
Console.WriteLine("Entered");
using (partition)
while (partition.MoveNext()){
var delay = partition.Current;
await Task.Delay(delay);
Console.WriteLine(string.Format("Waited {0} milliseconds",delay));
}
}));
Console.WriteLine("Done");
}
}
执行似乎在Task.Delay(延迟)之后停止:
Starting.
Entered
Entered
Waited 0 milliseconds
Entered
Entered
Entered
Entered
Entered
Entered
Entered
Entered
推荐答案
简短答案
更改您的Main
定义以返回Task
:
public async static Task Main()
更长的答案
实际上,异步方法最初是同步运行的,直到第一个await
.如果通过您调用的任何方法(在本例中为Task.WhenAll
)返回的Task
尚未完成,则await
关键字通过将Task
返回到调用方法并签名来使事情变得异步.该方法的其余部分作为该Task
的延续.
Asynchronous methods actually run synchronously at first, up until the first await
. If the Task
that is returned by whatever method you called (Task.WhenAll
in this case) has not completed yet, then the await
keyword makes things asynchronous by returning a Task
to the calling method, and signing up the rest of the method as a continuation on that Task
.
因此,这意味着您的Main
方法实际上在命中第一个Task.Delay()
之后返回,因为它返回了Task
,这触发了Task.Run
返回了Task
,从而触发了Task.WhenAll()
返回了Task
.由于您的Main
方法返回void
,因此.NET不知道任何内容仍在运行,并且您的程序结束了.
So that means that your Main
method actually returns after the first Task.Delay()
is hit, beacuse that returns a Task
, which triggers Task.Run
to return a Task
, which triggers Task.WhenAll()
to return a Task
. Since your Main
method returns void
, then .NET has no idea anything is still running and your program ends.
如果返回Task
,则.NET将等待直到Task
完成.
If you return a Task
, then .NET will wait until that Task
is completed.
If you want, there is extra reading here about the valid Main
signatures.
请注意,async
方法签名仅在C#7.1+中有效.如果无法使用C#7.1+,则可以从Main
方法中删除async
并使用
Note that the async
method signatures only work in C# 7.1+. If you can't use C# 7.1+, then you can remove async
from the Main
method and use Task.WaitAll()
instead of await Task.WhenAll()
(but you also have to call .ToArray()
on the collection, since WaitAll()
doesn't have an overload that accepts IEnumerable<Task>
like WhenAll()
does). That will block the main thread, but it's not really a big deal in a console app.
这篇关于委托中Task.Delay之后的代码未执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!