while(true)+ Task.Delay()在async void方法中;我应该预料到麻烦吗?

时间:2016-10-05 07:11:19

标签: .net wpf async-await

我没有手动摆弄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开始)并且打算在整个应用程序运行时运行。

单个问题

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

2 个答案:

答案 0 :(得分:2)

  

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

不是真的。但是有一些事情需要注意。

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

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

还会有更多的“抖动”。在幕后发生的事情是Task.Delay启动线程池计时器,当它触发时,它将完成任务;此时,StartWatching的延续已安排到UI线程,并且在执行其工作之前,它将耐心地等待UI线程空闲。所以会有一个额外的“等待UI线程”需要花费不同的时间 - 通常是立即的,但有时候等待所有的UI绑定更新,...

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

答案 1 :(得分:1)

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

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

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