委托中Task.Delay之后的代码未执行 [英] Code after Task.Delay in delegate not executing

查看:357
本文介绍了委托中Task.Delay之后的代码未执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试同时处理列表的分区.对于列表中每个分区中的每个整数,我都在等待那段时间.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆