Winforms UI线程编组BusinessObject列表正在从后台线程更新

时间:2009-07-02 20:53:46

标签: c# .net winforms

首先,我知道有许多问题和解决方案可以纠正来自后台线程以外的线程的线程编组。我发现的所有问题和解决方案都集中在列表或业务对象本身引发事件的场景中 Windows窗体可以订阅,然后将更新正确地编组到主UI线程。

在我的情况下,业务对象列表正在由单独的图层中的后台线程更新。我希望这个列表绑定到主线程上的控件。我是否真的需要从业务对象列表向UI公开事件,以便可以正确编组更新?我是否可以不安静地更新业务对象列表并将这些更新传播到UI,而不必以某种方式将列表更改事件公开给UI?

编辑:

我的问题基本上是这样的:在更改属性后触发了更改的INotifyProperty。绑定到实现此接口的对象的控件将尝试更新,如果导致事件触发的线程不是UI线程,则我们遇到问题。所以我们需要通知我们想要更新的UI线程,以便可以以线程安全的方式处理更新,这意味着后台线程更新对象不能简单地进行业务,它必须要求权限更新对象或要求UI代表它对对象进行更改。这就是我所说的UI被拉入句柄对象更新。

2 个答案:

答案 0 :(得分:1)

我在this old usenet post上发布了一个选项(包括示例) - 查找ThreadedBindingList(不要惊慌 - 大部分代码都是设置示例;列表类非常小);它可能会有所帮助,但IMO你可能会做得更好,只是稍后再做一次UI更新......

(不要错过帖子中较低的更新)

答案 1 :(得分:0)

我的经验是,如果您将业务对象绑定到UI,则必须在UI线程上隐式执行对这些对象所做的任何更改,否则您将获得跨线程异常。

当这些对象被数据绑定到UI时,从非UI线程更改对象是个坏消息。

请参阅,如果您的对象实现了绑定友好模式(例如INotifyPropertyChanged),并将这些对象中的一个/多个绑定到UI,那么您在幕后更新对象一种导致任何绑定友好事件加入UI的方式,你的'对象已经改变'通知使得它成为UI代码的方式,导致跨线程异常。

更新:绕过对象引发有问题的事件的一种方法是实现某种“STFU”对象级变量,当对象进行更新时可以将其设置为true从非UI线程状态。然后,在“OnRaiseMyEvent(...)”方法中,您可以检查STFU变量的状态 - 如果为true,则STFU,否则,引发事件。

更新#2:啊,对于问题的更新,这是我在这种情况下所做的:将ISynchronizeInvoke传递给业务对象的构造函数。然后,业务对象可以处理是否需要将事件引发封送到UI线程:

public class MyObject { 
   private ISynchronizeInvoke _Invoker;

   public MyObject(ISynchronizeInvoke invoker) { 
      _Invoker = invoker;
   }

   private void OnPropertyChanged(string propertyName) {
      PropertyChangedEventHandler handlers = this.PropertyChanged;
      if (handlers != null) { 
      if (_Invoker.InvokeRequired) { 
        _Invoker.Invoke(handlers, new PropertyChangedEventArgs(propertyName)); 
      } else { 
         handlers(new PropertyChangedEventArgs(propertyName);
      }
   }
}