C#异步等待Task.Delay在实践中的应用

4

我遇到了一些问题,无法使任务异步延迟。我正在编写一个需要以数万/数十万个异步执行脚本的规模运行的应用程序。我使用C# Actions来实现这一点,有时,在执行特定序列期间,为了使脚本正常执行,它需要等待外部资源达到预期状态。起初,我使用Thread.Sleep()来实现,但这导致应用程序性能下降,因此我正在研究异步休眠的async/await。但是我无法让它真正等待暂停!有人能解释一下吗?

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个回答

7
你遇到了一个关于async void的问题。当你将一个async lambda传递给Action时,编译器会为你创建一个async void方法。
作为最佳实践,应该避免使用async void。
一种方法是将你的操作列表实际上作为List>而不是List。这样可以让你排队async Task方法而不是async void方法。
这意味着你的“执行”代码必须等待每个Task完成。此外,你的同步方法必须返回Task.FromResult(0)或类似的内容,以便与Func签名匹配。
如果你想要更大范围的解决方案,我强烈建议你考虑使用TPL Dataflow而不是创建自己的队列。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接