wpf 异步友好 DispatcherTimer 包装器/子类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12442622/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Async friendly DispatcherTimer wrapper/subclass
提问by Simon_Weaver
I have a DispatcherTimerrunning 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/ awaitfriendly DispatcherTimer.
我DispatcherTimer在我的代码中运行,每 30 秒触发一次以从服务器更新系统状态。即使我正在调试我的服务器代码,计时器也会在客户端触发,所以如果我已经调试了 5 分钟,我可能会在客户端出现十几个超时。最后决定我需要解决这个问题,所以希望制作一个更async/await友好的 DispatcherTimer。
- Code running in
DispatcherTimermust 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
awaiton 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
IsRunningfor UI
DispatcherTimer无论是否可重入,运行的代码都必须是可配置的(即,如果任务已经在运行,则不应尝试再次运行它)- 应该是基于任务的(无论这是否需要我在根部实际公开 Task 是一个灰色区域)
- 应该能够运行异步代码并
await完成任务 - 它是否包装或扩展 DispatcherTimer 可能并不重要,但如果您不知道如何使用它,包装它可能会稍微不那么模糊
- 可能
IsRunning为 UI公开可绑定属性
回答by Simon_Weaver
Here's what I came up with.
这是我想出的。
SmartDispatcherTimerExtendsDispatcherTimer(was easiest way to get this up and running)- Has a
TickTaskproperty to provide aTaskto handle the logic - Has an
IsReentrantproperty (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
SmartDispatcherTimer扩展DispatcherTimer(是启动和运行的最简单方法)- 有一个
TickTask属性来提供一个Task来处理逻辑 - 有一个
IsReentrant属性(当然,重点是我希望它不能重入,所以通常这是错误的) - 它假设您调用的任何内容都是完全可等待的 - 否则您最终将失去重入保护的好处
Usage:
用法:
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; }
}

