WPF UI定时器线程更新

3

在应用程序中,我展示了随着时间推移或用户点击“下一个/上一个”而旋转的横幅。

1)我需要在 Timer.Elapsed 方法中更新 UI 元素。根据我所找到的信息,似乎计时器的 tick 是在它们自己的线程上执行的,应该使用元素的 dispatcher 更新 UI。

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

但是这会抛出一个 InvalidOperationException 异常。

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


只需使用 DispatcherTimer 而不是 Timer - Sheridan
每个线程都有一个Dispatcher,因此您可能没有使用来自UI线程的Dispatcher。为确保您正在使用它,可以使用Application.Current.Dispatcher对象。另请参见Dispatcher.CurrentDispatcher vs. Application.Current.Dispatcher以获取更多信息。但是,DispatcherTimer是此工作的正确工具,因为它避免了使用Dispatcher对象的任何需要。 - Sheridan
2个回答

3

好的,你知道我试图进行调度程序调用时出了什么问题吗?只是为了参考。 - pikausp
@pikausp,看一下我在你的问题上的评论,那个答案是我目前认为最好的答案。 - Sheridan

1
尝试使用Application代替,
Application.Current.Dispatcher.Invoke(new Action(() => 
{
    ((Image)BannerPanel.Content).Source = GetImage(new Uri(banner.Uri, UriKind.Absolute));
});

它不再崩溃了,但我已经按照其他人的建议切换到使用DispatcherTimer。 - pikausp
@pikausp,是的,当涉及到你的情况时,DispatcherTimer更为适用。不过,这是另一种选择。我建议在想要执行Invoke或BeginInvoke时使用Application.Current。 - d.moncada

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接