异步友好 DispatcherTimer 包装器/子类 [英] Async friendly DispatcherTimer wrapper/subclass

查看:19
本文介绍了异步友好 DispatcherTimer 包装器/子类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 DispatcherTimer 在我的代码中运行,它每 30 秒触发一次以从服务器更新系统状态.即使我正在调试我的服务器代码,计时器也会在客户端触发,所以如果我已经调试了 5 分钟,我可能会在客户端出现十几个超时.最后决定我需要解决这个问题,所以希望制作一个更async/await 友好的 DispatcherTimer.

I have a DispatcherTimer running in my code that fire every 30 seconds to update system status from the server. The timer fires in the client even if I'm debugging my server code so if I've been debugging for 5 minutes I may end up with a dozen timeouts in the client. Finally decided I needed to fix this so looking to make a more async / await friendly DispatcherTimer.

  • DispatcherTimer 中运行的代码必须是可配置的,无论它是否可重入(即,如果任务已经在运行,则不应尝试再次运行它)
  • 应该是基于任务的(无论这是否需要我在根部实际暴露任务是一个灰色区域)
  • 应该能够运行异步代码并await完成任务
  • 它是否包装或扩展 DispatcherTimer 可能并不重要,但如果您不知道如何使用它,包装它可能会稍微不那么模糊
  • 可能为 UI 公开 IsRunning 的可绑定属性
  • Code running in DispatcherTimer must be configurable whether it is reentrant or not (i.e. if the task is already running it should not try to run it again)
  • Should be task based (whether or not this requires I actually expose Task at the root is a gray area)
  • Should be able to run async code and await on tasks to complete
  • Whether it wraps or extends DispatcherTimer probably doesn't really matter but wrapping it may be slightly less ambiguous if you don't know how to use it
  • Possibly expose bindable properties for IsRunning for UI

推荐答案

这是我的想法.

  • SmartDispatcherTimer 扩展 DispatcherTimer(这是启动和运行的最简单方法)
  • 有一个 TickTask 属性来提供一个 Task 来处理逻辑
  • 有一个 IsReentrant 属性(当然,重点是我希望它不是可重入的,所以通常这是错误的)
  • 它假设您调用的任何内容都是完全可等待的 - 否则您最终将失去重入保护的好处
  • SmartDispatcherTimer Extends DispatcherTimer (was easiest way to get this up and running)
  • Has a TickTask property to provide a Task to handle the logic
  • Has an IsReentrant property (of course the whole point is that I want it to not be reentrant so normally this is false)
  • It assumes anything you're calling is fully awaitable - or you'd end up losing the reentrancy protection benefits

用法:

        var timer = new SmartDispatcherTimer();
        timer.IsReentrant = false;
        timer.Interval = TimeSpan.FromSeconds(30);
        timer.TickTask = async () =>
        {
            StatusMessage = "Updating...";  // MVVM property
            await UpdateSystemStatus(false);
            StatusMessage = "Updated at " + DateTime.Now;
        };
        timer.Start();

这是代码.很想听听关于它的任何想法

Here's the code. Would love to hear any thoughts on it

public class SmartDispatcherTimer : DispatcherTimer
{
    public SmartDispatcherTimer()
    {
        base.Tick += SmartDispatcherTimer_Tick;
    }

    async void SmartDispatcherTimer_Tick(object sender, EventArgs e)
    {
        if (TickTask == null)
        {
            Debug.WriteLine("No task set!");
            return;
        }

        if (IsRunning && !IsReentrant)
        {
            // previous task hasn't completed
            Debug.WriteLine("Task already running");
            return;
        }

        try
        {
            // we're running it now
            IsRunning = true;

            Debug.WriteLine("Running Task");
            await TickTask.Invoke();
            Debug.WriteLine("Task Completed");
        }
        catch (Exception)
        {
            Debug.WriteLine("Task Failed");
        }
        finally
        {
            // allow it to run again
            IsRunning = false;
        }
    }

    public bool IsReentrant { get; set; }
    public bool IsRunning { get; private set; }

    public Func<Task> TickTask { get; set; }
}

这篇关于异步友好 DispatcherTimer 包装器/子类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆