我如何创建一个由代理堆栈组成的异步结构,并弹出它们并每N毫秒调用一次它们?
现在的问题是,我有很多委托在ui上调用更改,这会导致ui冻结,因此,如果堆栈不为空,如何使此委托每N ms调用一次。
现在我有了
class CallbackRestriction
{
private Stack<KeyValuePair<Action<ImageWrapper>, ImageWrapper>> _callbackList =
new Stack<KeyValuePair<Action<ImageWrapper>, ImageWrapper>>();
public void AddCallback(Action<ImageWrapper> action, ImageWrapper payload)
{
_callbackList.Push(new KeyValuePair<Action<ImageWrapper>, ImageWrapper>(action, payload));
}
private async Task CallbackEmitLoop()
{
while (true)
{
await Task.Delay(TimeSpan.FromMilliseconds(20));
try
{
var callback = _callbackList.Pop();
callback.Key.Invoke(callback.Value);
}
catch (Exception e)
{
await Task.Delay(200);
}
}
}
}
但是如何使CallbackEmitLoop
在后台启动?或任何其他解决方案?
更新1
我不需要Dispather计时器,因为它已被WPF所限制,也许对于“计时器”而言,我应该使用同步上下文。而且从其他上下文调用我的集合也没有问题,因为可以使集合为并发就绪。我需要一个类似阀门的东西,一旦添加代表,它将限制调用代理。所以我在上面描述问题的方式可以一次获得很多“更新”(代理),如果我仅应用它们(调用委托),则ui线程将花费大量时间,这将导致冻结,因此我应该以某种方式保留时间,然后再应用下一次“更新”。
答案 0 :(得分:0)
这是一种方式。下面的代码使用您的CallbackRestriction类和ImageWrapper的虚拟实现。我已经公开了CallbackEmitLoop方法,以便我的窗口可以使用Task.Run启动它。
因为我在窗口中维护了委托发射器实例,所以只要窗口处于活动状态,它将一直运行。真正的应用可能会通过其他一些服务类别运行它。
如果回调需要与WPF UI元素一起使用,则回调需要使用Dispatcher在UI线程上调用代码,因为Task在线程池线程上运行,并且任何委托调用也将在该线程上运行。
关于这可能是一个重复问题的评论,OP正在询问如何让正在运行的Task调用与UI交互的委托,而DispatcherTimer当然是一种合理的方法,但它并未解决OP的问题,也没有提供关于为什么DispatcherTimer将是更合适的实现的解释。
./gradlew