WPF高度并发跨线程UI访问

时间:2014-08-08 17:35:56

标签: c# .net wpf multithreading

在C#中,我有几个工作,我需要将其反映到UI中。更新进度条,将项目添加到列表等等。

我第一次尝试这样做时,我使用锁来准备一切,以确保每个给定时刻只有一个线程访问UI但我得到了一个例外。所以我了解到我需要使用Dispatcher.Invoke来访问和更改UI元素。将每个UI更改封装到调用中非常麻烦,但我可以处理它。

我的问题:

  • 是否需要同步Dispatcher.Invoke次来电或内部完成?所以我想知道是否需要添加另一层带锁的保护......
  • 是否会影响排队到调度程序的许多更新请求的性能?因此,如果多个线程工作并且每个线程都通过一个小的更改反映到UI中,那么如何向Dispatcher.Invoke发出许多调用`影响表现?我应该使用计时器并且每秒只更新一次UI并在内部排队所有UI更改吗?
  • 是否有更简单的方法可以更直接地进行跨线程访问...没有调用?

2 个答案:

答案 0 :(得分:7)

人脑无法处理200次更新/秒。它只会减慢你的用户界面,而不会让你获得任何东西。

相反,制作一个定时器,每个轮询状态,比如200ms。这将足够快(5次更新/秒),不会引人注意。

无需锁定调度程序,它在内部处理。但是你应该将你的任务专门用于计算,而不是从他们那里操纵UI。像我说的那样实现一个计时器,并使用一些标准的跨线程通信方式从UI线程中检索当前状态。

答案 1 :(得分:3)

  

是否有必要同步Dispatcher.Invoke调用或内部完成?所以我想知道我是否需要用锁添加另一层保护......

不,这是多余的。

  

是否会影响排队到调度员的许多更新请求的性能?因此,如果多个线程工作并且每个线程都通过一个小的更改反映到UI中,那么对Dispatcher.Invoke`发出许多调用会如何影响性能?我应该使用计时器并且每秒只更新一次UI并在内部对所有UI更改进行排队吗?

如果你使用Invoke而不是BeginInvoke,你就不会填满队列(除非你有太多的线程),每个线程都会等待它的动作由调度员。

垃圾邮件调度程序可能会影响性能。您不需要经常更新UI。如果你经常等待调度员,你只会浪费时间而失去多线程的好处。

更好的选择是调用BeginInvoke并不经常这样做以避免压倒主线程。这样,在等待UI更新时,您不会浪费处理线程的时间。

  

是否有一种更简单的方法来进行跨线程访问更多内联...没有Invokes?

  1. 如果您可以将工作人员代码内联,则async / await:

    UpdateUI();
    await Task.Run(...);
    UpdateUI();
    
  2. 如果您使用Paraller.ForEach,则可以将进度值放入可变,原子递增的位置,并使用计时器更新UI。