C# async await Task.delay 实战

标签 c# asynchronous action async-await

我在让任务异步延迟时遇到了一些麻烦。我正在编写一个需要以数十/数十万个异步执行脚本的规模运行的应用程序。我正在使用 C# Actions 执行此操作,有时,在执行特定序列期间,为了使脚本正确执行,它需要等待外部资源达到预期状态。起初我使用 Thread.Sleep() 编写了这个,但事实证明这是应用程序性能的鱼雷,所以我正在研究异步/等待异步 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();
        }
    }

执行结果为:

Sync: 999

Async: 2

如何让它异步等待?

最佳答案

您遇到了 async void 的问题.当你通过 async lambda 到 Action ,编译器正在创建一个 async void方法给你。

作为最佳实践,您应该避免 async void .

实现此目的的一种方法是让您的操作列表实际上是一个 List<Func<Task>>而不是 List<Action> .这允许您排队 async Task方法而不是 async void方法。

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

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

关于C# async await Task.delay 实战,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17555753/

相关文章:

c# - 您需要使用 Invoke on Action 吗?

node.js - Node 使用回调或事件异步提取 zip 文件?

c# - 序列化 xml 文件的一部分。希望命名空间位于根元素上,而不是序列化的子元素上

c# - 为什么 int.Max+ int.Max = -2

c# - 返回玩家组合的有效方法

java - 在 log4j2 AsyncLogger 中传递 threadId 的最佳方法

node.js - Node 并发/快速请求生命周期/可能的竞争条件?

类的 Java 菜单栏操作

java - 将单个字符串与 JList<String> 一起用于操作

c# - 复杂类型 : multiple instances in one model?