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

  • DispatcherTimer 中运行的代码必须是可配置的,无论它是否可重入(即,如果任务已经在运行,则不应尝试再次运行它)
  • 应该是基于任务的(不管这是否需要我实际上在根处暴露 Task 是一个灰色区域)
  • 应该能够在任务上运行异步代码和 await 来完成
  • 是否包装或扩展 DispatcherTimer 可能并不重要,但如果您不知道如何使用它,包装它可能会稍微不那么模糊
  • 可能为 UI
  • 公开 IsRunning 的可绑定(bind)属性

    最佳答案

    这是我想出的。

  • SmartDispatcherTimer 扩展 DispatcherTimer(是启动和运行的最简单方法)
  • 有一个 TickTask 属性来提供一个 Task 来处理逻辑
  • 有一个 IsReentrant 属性(当然重点是我希望它不能重入,所以通常这是错误的)
  • 它假设您调用的任何内容都是完全可等待的 - 否则您最终将失去重入保护的好处

  • 用法:
            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();
    

    这是代码。很想听听关于它的任何想法
    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; }
    }
    

    关于c# - 异步友好 DispatcherTimer 包装器/子类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12442622/

    10-09 18:28