从计时器线程的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)横幅控制器提供Next
和Previous
方法,分别调用display next/previous banner。由于DisplayBanner
方法尝试显示横幅,当文件未找到时,它会尝试使用WebClient
的AsyncFileDownload
和DownloadComplete
重新下载它,它会显示图像。我是否正确地假设定时器启动的Elapsed
和Next
/Previous
的手动调用都可以同时发生,两者都在它们自己的线程上运行(在UI线程上为Previous
/Next
,在定时器线程上为Elapsed
),这可能导致不稳定?
您应该使用DispatcherTimer
类而不是常规Timer
进行调查。它旨在与WPF UI一起使用,仅用于这些类型的用途,因为它在Dispatcher
线程上运行。
尝试使用应用程序来代替,
Application.Current.Dispatcher.Invoke(new Action(() =>
{
((Image)BannerPanel.Content).Source = GetImage(new Uri(banner.Uri, UriKind.Absolute));
});
它不再崩溃,但我转而使用其他人推荐的DispatcherTimer。 – pikausp 2014-09-04 15:41:43
@pikausp,是的,当涉及到你的情况时,DispatcherTimer更具有热门性。不过,这是另一种选择。我会建议使用Application.Current每当你想做一个Invoke或BeginInvoke。 – 2014-09-04 15:44:33
只需使用而不是'Timer'一个'DispatcherTimer'。 – Sheridan 2014-09-04 15:11:56
每个*线程都有一个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