C#async等待Action.delay在Action中

时间:2013-07-09 18:40:19

标签: c# asynchronous action async-await

我在完成异步延迟任务时遇到了一些麻烦。我正在编写一个需要以数十/数十万个异步执行脚本的规模运行的应用程序。我正在使用C#Actions执行此操作,有时,在执行特定序列期间,为了使脚本正确执行,它需要等待外部资源才能达到预期状态。起初我使用Thread.Sleep()编写了这个,但结果却是应用程序性能的鱼雷,所以我正在研究async / await for async sleep。但我无法让它真正等待暂停!有人可以解释一下吗?

static void Main(string[] args)
    {
        var sync = new List<Action>();
        var async = new List<Action>();

        var syncStopWatch = new Stopwatch();
        sync.Add(syncStopWatch.Start);
        sync.Add(() => Thread.Sleep(1000));
        sync.Add(syncStopWatch.Stop);
        sync.Add(() => Console.Write("Sync:\t" + syncStopWatch.ElapsedMilliseconds + "\n"));

        var asyncStopWatch = new Stopwatch();
        sync.Add(asyncStopWatch.Start);
        sync.Add(async () => await Task.Delay(1000));
        sync.Add(asyncStopWatch.Stop);
        sync.Add(() => Console.Write("Async:\t" + asyncStopWatch.ElapsedMilliseconds + "\n"));

        foreach (Action a in sync)
        {
            a.Invoke();
        }

        foreach (Action a in async)
        {
            a.Invoke();
        }
    }

执行结果如下:

  

同步:999

     

异步:2

如何让它等待异步?

1 个答案:

答案 0 :(得分:7)

您遇到了async void的问题。将async lambda传递给Action时,编译器会为您创建async void方法。

作为最佳做法,您应该避免使用async void

执行此操作的一种方法是让您的操作列表实际上是List<Func<Task>>而不是List<Action>。这允许您对async Task方法进行排队,而不是async void方法。

这意味着你的执行&#34;代码必须等待每个Task完成。此外,您的同步方法必须返回Task.FromResult(0)或类似的东西,以便它们与Func<Task>签名匹配。

如果您想要更大范围的解决方案,我建议您强烈考虑使用TPL Dataflow而不是创建自己的队列。