Winforms用户界面线程调度后台线程更新的BusinessObject列表

3
首先,我知道有许多问题和解决方案可以从非后台线程中正确地调用线程处理。我发现的所有问题和解决方案都专注于在列表或业务对象本身引发事件的情况下,Windows表单可以订阅并正确地将更新调度到主UI线程。
在我的情况下,业务对象列表由独立层中的后台线程更新。我希望将此列表绑定到主线程上的控件。我真的需要从业务对象列表向UI公开事件,以便可以正确地调度更新吗?我不能安静地更新业务对象列表并将这些更新传播到UI,而不必以某种方式向UI公开列表更改事件吗?
编辑:
我的问题本质上是这样的:在属性更改后触发INotifyPropertyChanged。绑定到实现此接口的对象的控件将尝试进行更新,如果导致事件触发的线程不是UI线程,则会出现问题。因此,我们需要通知UI线程,以便可以以线程安全的方式进行更新,这意味着更新对象的后台线程不能简单地进行操作,它必须请求权限来更新对象或要求UI代表其对对象进行更改。这就是我所说的UI被拉入处理对象更新的方式。
2个回答

1

我在这里发布了一个选项(包括示例)这个旧的Usenet帖子 - 查找ThreadedBindingList(不要惊慌 - 大多数代码是设置示例; 列表类非常小);它可能会有所帮助,但在我看来,您最好稍后执行UI更新...

(不要错过线程底部的更新)


那个 ThreadedBindingList 看起来非常不错。我想我会试着用一下。 - Fredrik Mörk
马克,你是在建议我允许 UI 处理更新吗? 请参阅我在 Yoopergeek 下面的评论。 - AndyMM
我说这是一个可能的选项。但是,这种跨线程工作确实会使事情变得更加复杂... - Marc Gravell
Marc,我刚刚测试了你的ThreadedBinding列表,非常好用,还有一些错误处理,我认为我可以使用它。谢谢。 - AndyMM

0

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

当非UI线程更改与UI数据绑定的对象时,情况不妙。

请注意,如果您的对象实现了绑定友好模式(例如INotifyPropertyChanged),并且您将其中一个/多个对象绑定到UI,并且在幕后以导致任何这些绑定友好事件到达UI的方式更新对象,则“对象已更改”通知正在传递到UI代码,从而导致跨线程异常。

更新:解决对象引发问题事件的一种方法是实现某种“STFU”对象级变量,该变量在从非UI线程更新对象状态时可以设置为true。然后,在您的“OnRaiseMyEvent(...)”方法中,您可以检查STFU变量的状态-如果为true,则保持静默,否则引发事件。

更新 #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);
      }
   }
}

我知道这正是问题所在!我正在实现那些绑定友好的接口。但是,如果我让UI处理我对业务对象所做的更新,我就会破坏封装性。UI被拉入处理更新,而这些更新本来不应该涉及UI。 - AndyMM
@Mule:“UI正在处理更新,这些更新实际上与其无关。”:嗯,但这正是你首先实现绑定接口的原因。. . . UI需要监听这些事件。 - Yoopergeek

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