【问题标题】:while(true) + Task.Delay() inside async void method; should I expect trouble?while(true) + Task.Delay() 在异步 void 方法中;我应该期待麻烦吗?
【发布时间】:2017-02-13 12:29:39
【问题描述】:

我没有手动摆弄 DispatcherTimer,而是想出了这个:

    public async void StartWatching()
    {
        Debug.Assert(SynchronizationContext.Current is DispatcherSynchronizationContext, "SynchronizationContext.Current is DispatcherSynchronizationContext");
        while ( true )
        {
            this.GC0 = GC.CollectionCount(0);
            this.GC1 = GC.CollectionCount(1);
            this.GC2 = GC.CollectionCount(2);
            this.RAM = GC.GetTotalMemory(false);
            await Task.Delay(1500);
        }
    }

这段代码不是垃圾收集,只是在状态栏上显示统计信息。

这会启动一次(从 Application.OnStartup 内部),旨在为整个应用程序运行时运行。

单个问题

长期(数周)运行时我会遇到任何麻烦吗?

【问题讨论】:

  • 为什么您需要手动启动垃圾回收?
  • @MikeEason 我只是在状态栏上显示统计数据。
  • 定时器的问题在哪里?这是计时器的用例,为什么需要替代方案?
  • 嗯,你特别在做一些会消耗资源(不必要的)的事情,每 1.5 秒,这会降低你的应用程序的性能。
  • @JeffRSon 如果我将Debug.Assert 重写为SynchronizationContext.Current != null,则代码变得与技术无关,并且可以跨 WPF、Winforms、Xamarin、Mobile 等使用。

标签: .net wpf async-await


【解决方案1】:

长期(数周)运行时我会遇到任何麻烦吗?

不是真的。不过,有些事情需要注意。

由于您的方法返回async void,任何异常都将直接在方法开始时的SynchronizationContext 上引发。因此,他们将直接转到调度程序(或 WinForms 的应用程序)。听起来这种行为可能是您想要的

延迟工作与使用定期计时器不同,尤其是在工作可能需要不同的时间时。所以,这段代码不会每 1.5 秒运行一次;它会比那少一些。但是,这样做的好处是您不必担心代码重叠,就像使用纯周期性计时器一样。

还会有更多的“抖动”。在幕后发生的事情是Task.Delay 启动了一个线程池 计时器,当它触发时,它将完成任务;那时,StartWatching 的延续被 调度 到 UI 线程,它会耐心等待 UI 线程空闲后再执行其工作。所以会有一个额外的“等待 UI 线程”,这将花费不同的时间 - 通常是立即的,但有时会等待所有 UI 绑定更新,...

最后,很小的延迟可能效果不佳。 WinForm 和 Dispatcher 计时器使用更高级的机制(直接内置到它们的消息循环中)来获得更高的准确性。由于Task.Delay 的额外开销,我相信在现实世界的应用程序中,它不适用于非常小的延迟。 (这只是直觉,不是测试结果)。

【讨论】:

    【解决方案2】:

    我个人认为,与使用DispatcherTimer相比,这种方法并没有什么特别糟糕的地方。就个人而言,我也使用了这种方法——它非常简短,而且直截了当。

    但是,请注意async 方法不会使您的应用程序崩溃 - 它们会在您不知情的情况下静默死亡。因此,您需要捕获您能想到的所有可能的异常。此外,async 方法中的任何 finally 块也不会运行。您还应该考虑在其中添加CancellationToken

    对于您的情况,我认为这不会导致问题。

    【讨论】:

    • 我无法确认这一点:在await 之前或之后抛出的异常幸运地冒泡到Application.DispatcherUnhandledException 事件。这不是async VOID的特长吗?
    猜你喜欢
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    • 1970-01-01
    • 2010-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多