C# 从计时器向WPF UI触发事件

C# 从计时器向WPF UI触发事件,c#,wpf,C#,Wpf,我有一个应用程序,它由一个WPF UI组成,它下面有一个“基础设施”层,其中有一些对各种数据服务的引用。我有一个类Updater,它有两个属性,表示UI层要使用的数据。这个更新程序有一个Systems.Timer函数,每隔一分钟左右,它就会对服务进行同步调用,并通过“刷新”数据来更新上述属性 我想从这个类中引发一个事件,当UI完成时可以将更改通知给它。当我在前面做类似的事情时,它会左右抛出异常,因为触发事件的线程不同(因为它来自计时器已过事件),然后创建对象的线程也不同 我现在使用的糟糕的解决方

我有一个应用程序,它由一个WPF UI组成,它下面有一个“基础设施”层,其中有一些对各种数据服务的引用。我有一个类Updater,它有两个属性,表示UI层要使用的数据。这个更新程序有一个Systems.Timer函数,每隔一分钟左右,它就会对服务进行同步调用,并通过“刷新”数据来更新上述属性

我想从这个类中引发一个事件,当UI完成时可以将更改通知给它。当我在前面做类似的事情时,它会左右抛出异常,因为触发事件的线程不同(因为它来自计时器已过事件),然后创建对象的线程也不同

我现在使用的糟糕的解决方案是在UI层上有另一个计时器,但是…糟糕


通知UI Updater类已完成其工作的最佳方式是什么?

这些跨线程异常可以通过
Dispatcher.Invoke
函数更新UI来解决。
Dispatcher
是一个可用于调用UI线程的对象。仔细阅读一下,你应该已经准备好了。

最好的方法是通过绑定,如果你能做到的话。使用数据类实现
System.ComponentModel.INotifyPropertyChanged
接口,然后将UI元素绑定到要显示的这些类的属性。更新属性时,它们会触发
PropertyChanged
事件,该事件由WPF依赖项对象在内部处理,并自动更新UI。这是一种避免很多管道的方法,通常情况下,您需要自己组装这些管道来响应更新


博客文章提供了一个很好的例子,说明了如何使用它,但网上还有很多其他的例子。

@impledged:Charlie的答案很好(+1)。一个警告:忽略链接文章的最后三段,因为它包含不准确的信息:您通常不应该使用CheckAccess。在StackOverflow上的其他位置搜索我的答案以了解详细信息。否则那篇文章就是一个很好的资源。我想我试过了,结果它死得很惨。明天我会试试这个,并在应该得到表扬的地方给予表扬。我想这是我的功劳——我不知道为什么它第一次对我不起作用,但我很确定我没有正确地使用它。我从基础结构层上的TimeRecursed函数触发一个事件,它由UI层处理。UI上的函数调用被包装在Dispatcher.Invoke()中。如果您从非UI线程设置属性,这仍然会引发异常。这可能是一种很好的方法,但我们正在寻找更快捷、更脏的方法。Rusty的评论是正确的;虽然这是更新绑定属性的好方法,但它不会阻止跨线程异常。@Rusty,@Charlie以下是通过绑定从异步操作实现UI更新的示例。我错过什么了吗@拉斯蒂,你能再解释一下吗?我的示例清楚地显示了通过异步调用进行的UI更新,而无需封送处理。