异步友好的DispatcherTimer包装器/子类

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

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

这就是我想出的。

  • 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 TickTask { get; set; } }