【问题标题】:WPF UI update from a timer thread从计时器线程更新 WPF UI
【发布时间】:2014-09-04 23:30:05
【问题描述】:

在应用程序中,我会显示随着时间的推移或用户单击下一个/上一个而旋转的横幅。

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 方法,分别在调用时显示下一个/上一个横幅。当DisplayBanner 方法尝试显示横幅时,当找不到文件时,它会尝试使用WebClientAsyncFileDownload 重新下载它,并在DownloadComplete 上显示图像。我是否正确假设计时器触发的ElapsedNext/Previous 的手动调用可以同时发生,两者都在自己的线程上运行(Previous/Next 在 UI 上thread 和 Elapsed 在 Timer thread 上),可能导致不稳定?

【问题讨论】:

  • 只需使用DispatcherTimer 而不是Timer
  • 每个线程都有一个Dispatcher,因此您可能没有使用 UI 线程中的那个。为确保您是,您可以使用Application.Current.Dispatcher 对象。另请参阅Dispatcher.CurrentDispatcher vs. Application.Current.Dispatcher 了解更多信息。但是,DispatcherTimer 是这项工作的正确工具,因为它避免了使用 Dispatcher 对象的任何需要。

标签: c# wpf multithreading timer dispatcher


【解决方案1】:

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

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

【讨论】:

  • 好的,但是你知道我试图做的调度员呼叫有什么问题吗?仅供参考。
  • @pikausp,请参阅我对您的问题的评论以获得该答案。这是我认为目前最好的答案。
【解决方案2】:

尝试改用应用程序,

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

【讨论】:

  • 它不再崩溃了,但我改用了其他人推荐的 DispatcherTimer。
  • @pikausp,是的,当涉及到您的情况时,DispatcherTimer 更具话题性。不过,这是另一种选择。我建议您在想要执行 Invoke 或 BeginInvoke 时使用 Application.Current。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多