从计时器线程的WPF UI更新

问题描述:

在应用程序中,我显示随时间推移或用户单击下一个/上一个时会旋转的横幅。从计时器线程的WPF UI更新

1)我需要更新Timer.Elapsed方法中的UI元素。从我发现的看来,计时器滴答是在他们自己的线程上执行的,元素的分派器应该用来更新UI。

((Image)BannerPanel.Content).Dispatcher.Invoke(new Action(() => { 
    ((Image)BannerPanel.Content).Source = GetImage(new Uri(banner.Uri, UriKind.Absolute)); 
})); 

但是抛出了InvalidOperationException

2)横幅控制器提供NextPrevious方法,分别调用display next/previous banner。由于DisplayBanner方法尝试显示横幅,当文件未找到时,它会尝试使用WebClientAsyncFileDownloadDownloadComplete重新下载它,它会显示图像。我是否正确地假设定时器启动的ElapsedNext/Previous的手动调用都可以同时发生,两者都在它们自己的线程上运行(在UI线程上为Previous/Next,在定时器线程上为Elapsed),这可能导致不稳定?

+0

只需使用而不是'Timer'一个'DispatcherTimer'。 – Sheridan 2014-09-04 15:11:56

+0

每个*线程都有一个Dispatcher,因此您可能不会使用UI线程中的一个。为了确保您可以使用Application.Current.Dispatcher对象。另请参阅[Dispatcher.CurrentDispatcher vs. Application.Current.Dispatcher](http://*.com/questions/10448987/dispatcher-currentdispatcher-vs-application-current-dispatcher)以获取更多信息。然而,'DispatcherTimer'是这个工作的正确工具,因为它避免了使用'Dispatcher'对象的任何需要。 – Sheridan 2014-09-04 15:34:58

您应该使用DispatcherTimer类而不是常规Timer进行调查。它旨在与WPF UI一起使用,仅用于这些类型的用途,因为它在Dispatcher线程上运行。

更多信息:System.Windows.Threading.DispatcherTimer

+0

好的,但是你知道我正在尝试执行调度程序调用的问题吗?仅供参考。 – pikausp 2014-09-04 15:17:01

+0

@pikausp,请参阅我对你的问题的评论。这在我看来是最好的答案。 – Sheridan 2014-09-04 15:36:49

尝试使用应用程序来代替,

Application.Current.Dispatcher.Invoke(new Action(() => 
{ 
    ((Image)BannerPanel.Content).Source = GetImage(new Uri(banner.Uri, UriKind.Absolute)); 
}); 
+0

它不再崩溃,但我转而使用其他人推荐的DispatcherTimer。 – pikausp 2014-09-04 15:41:43

+0

@pikausp,是的,当涉及到你的情况时,DispatcherTimer更具有热门性。不过,这是另一种选择。我会建议使用Application.Current每当你想做一个Invoke或BeginInvoke。 – 2014-09-04 15:44:33