代码之家  ›  专栏  ›  技术社区  ›  stakx - no longer contributing Saravana Kumar

Winforms数据绑定到多线程场景中的业务对象而不需要调用?

  •  1
  • stakx - no longer contributing Saravana Kumar  · 技术社区  · 14 年前

    例如,我有一个业务对象 Person

    class Person : INotifyPropertyChanged
    {
        string Name { get; set; }
        DateTime DateOfBirth { get; set; }
    }
    // ^ abbreviated for better legibility; implementation would be trivial
    

    我有一些Winforms UI控件数据绑定到这个类的一个对象上:

    Person somePerson = ...;
    nameTextBox.DataBindings.Add("Text", somePerson, "Name");
    dobDatePicker.DataBindings.Add("Value", somePerson, "DateOfBirth");
    

    现在我正在对 somePerson 多亏有了 INotifyPropertyChanged 实现后,这些更改将反映在UI中。到现在为止,一直都还不错。

    现在我的问题是: 如果我更改 某人 在工作线程(即不在UI线程中)中,例如,因为我正在从DB加载数据作为后台操作,这可能会导致异常,因为数据绑定尝试更新控件,这只允许在UI线程上发生。

    这意味着我需要打电话 InvokeRequired 在UI元素上查看是否允许我更新业务对象-这看起来像 .

    1 回复  |  直到 14 年前
        1
  •  3
  •   Tim Robinson    14 年前

    这不能回答你的问题,但我尽量避免这个问题。

    由于数据绑定的存在,我确保唯一可以更新业务对象的代码是在GUI线程上运行的代码。

    1. 将工作发送到后台: 从GUI线程触发一个异步操作(比如线程池项)。只将普通数据类型传递到线程池,并只接收普通数据类型。如果线程池使用业务对象,请确保这些对象是全新的(尚未绑定数据),或者是原始对象的克隆(以避免并发访问)
    2. 在后台线程上执行异步操作。后台线程代码将拥有GUI提供给它的“安全”对象;它不会与应用程序的其余部分进行任何交互。
    3. 当异步操作完成时,它会在GUI线程上触发一个'I am complete'事件。作为响应,GUI线程可以解包后台操作的任何结果,并将它们合并回主业务对象,因为它不会处理并发访问。

    我可以推荐 System.Threading.Tasks.Task 类作为围绕上述大多数步骤的抽象。它是.NET4.0中的新版本,但也可以作为.NET3.5应用程序的单独下载。

    Task 类没有任何定制。你可以通过产生一个单独的 任务 从后台线程内部 TaskScheduler.FromCurrentSynchronizationContext FromCurrentSynchronizationContext 在步骤(1)中,从GUI线程,而不是从后台线程。)

    推荐文章