异步友好的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; } }