绑定数据更改时Winforms列表框不更新

Tob*_*bbe 5 c# data-binding multithreading listbox winforms

下图显示了我的代码的工作原理.当我按下按钮2时,列表框会更新,但不会在我按下按钮1时更新.为什么?

伪代码http://i44.tinypic.com/mj69oj.gif

问题线程是否相关?如果是,我应该在哪里添加对(Begin)Invoke的调用?

需要注意的一件有趣的事情是,如果我先按下button1然后按下按钮2,则单击button2时会显示button1单击生成的数据.所以似乎doFoo生成的数据在某处缓冲,然后在按下button2后推送到列表框.

编辑:

我尝试将AddNumber添加到表单代码中,并在listBox1.InvokeRequired返回true时添加对Invoke的调用.这解决了问题,但不是最好的设计.我不希望GUI必须"担心"如何将项添加到模型的一部分列表中.

如何在添加到列表类内部列表的同时保持逻辑,同时在列表更改时仍然更新gui?

编辑2:

现在我们已经确认这是一个线程问题,我已经更新了图像,以便更接近地反映我正在处理的实际代码的设计.

虽然Lucero的建议仍然解决了这个问题,但我希望能找到一些不需要表格来了解dll或CDllWrapper的东西.

模型(ListBoxDataBindingSource等)应该对视图(列表框,按钮,标签等)一无所知

Luc*_*ero 2

我的猜测是,这是由于更新消息在错误的线程上处理的。背景:每个线程都有自己的消息队列。默认情况下,发布到消息队列中的消息将与调用者位于同一线程中。因此,回调可能会在错误的线程上发布消息。

尝试以下操作:将 AddNumber() 方法移至窗体并使用 Invoke()(由 Control 继承)在正确的线程中添加项目。这可能会解决这个问题。

编辑以反映您的后续行动:UI 不必了解您的组件。您需要的只是将项目添加到列表和 UI 之间的适当同步,因为 UI 更新只有在线程匹配时才会起作用。因此,您可能需要向包装 BindingList 的类提供 Control,然后对列表本身执行 Invoke。这使得列表担心触发 UI 线程上的更新,并且确实消除了 UI 和外部组件在正确线程上调用处理程序的担心。

像这样:

internal class ListBoxDataBindingSource {
  private readonly Control uiInvokeControl;
  private readonly BindingList<Item> list = new BindingList<Item>();

    public ListBoxDataBindingSource(Control uiInvokeControl) {
      if (uiInvokeControl == null) {
            throw new ArgumentNullException("uiInvokeControl");
      }
        this.uiInvokeControl = uiInvokeControl;
        CDIIWrapper.setFP(AddNumber);
    }

    public void AddNumber(int num) {
      Item item = new Item(num.ToString());
        if (uiInvokeControl.InvokeRequired) {
            uiInvokeControl.Invoke(list.Add, item);
        } else {
            list.Add(item);
        }
    }

    private BindingList<Item> List {
        get {
            return list;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)