Winforms在没有InvokeRequired的情况下在多线程方案中将数据绑定到业务对象? [英] Winforms data-binding to business objects in a multi-threaded scenario without InvokeRequired?

查看:113
本文介绍了Winforms在没有InvokeRequired的情况下在多线程方案中将数据绑定到业务对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

For example, I've got a business object Person:

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

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

And I've got some Winforms UI controls data-bound to an object of this class:

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

现在我要对somePerson进行更改,并且由于实现了INotifyPropertyChanged,这些更改将反映在UI中.到目前为止一切顺利.

Now I am making changes to somePerson and thanks to having INotifyPropertyChanged implemented, those changes are reflected in the UI. So far so good.

现在是我的问题:如果我在工作线程(即不在UI线程中)中对somePerson进行了更改,例如因为我从数据库中将数据作为后台操作加载,所以这可能会导致异常,因为数据绑定尝试更新控件,而这仅允许在UI线程上进行.

Now to my problem: If I make changes to somePerson in a worker thread (ie. not in the UI thread), e.g. because I'm loading data from a DB as a background operation, this might cause exceptions because the data binding attempts to update the controls, which is only allowed to happen on the UI thread.

这意味着我需要在UI元素上调用InvokeRequired,以查看是否允许我更新业务对象—.这似乎是违反了应用程序的逻辑层.

This means that I need to call InvokeRequired on a UI element to see if I'm allowed to update a business object — which seems like a violation of the application's logical layering.

理想情况下,我希望能够修改我的业务对象,而不必关心它是否与UI数据绑定. Winforms数据绑定是否可以通过某种方式实现?

Ideally, I want to be able to modify my business objects without having to care whether it is data-bound to the UI or not. Is this somehow possible with Winforms data binding, or not?

推荐答案

这不能回答您的问题,但我会尽力避免此问题.

This doesn't answer your question, but I try as far as possible to avoid this problem.

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

Because of the existence of data binding, I make sure the only code that can update business objects is code that's running on the GUI thread.

对于异步操作,我采用以下模式:

For async operations, I adopt a pattern of:

  1. 将工作发送到后台::从GUI线程触发异步操作(例如线程池项).仅将纯数据类型传递到线程池中,而仅接收回纯数据类型.如果线程池使用了业务对象,请确保它们是全新的对象(尚未绑定数据),或者是原始对象的克隆(以避免并发访问)
  2. 完成工作并获得结果:在后台线程上执行异步操作.后台线程代码将拥有GUI赋予它的安全"对象.它不会与应用程序的其余部分进行任何交互.
  3. 在GUI中解压结果:异步操作完成后,它将在GUI线程上触发我已完成"事件.作为响应,GUI线程可以解包来自后台操作的任何结果,并将它们合并回主要业务对象中,这是安全的,因为它不会处理并发访问.
  1. Send work to the background: Trigger an async operation -- say, a thread pool item -- from the GUI thread. Pass only plain data types into the thread pool, and receive only plain data types back. If business objects are used by the thread pool, make sure that these are either brand new ones (that haven't been data bound yet), or are clones of the originals (to avoid concurrent access)
  2. Do the work and obtain a result: Execute the async operation on a background thread. The background thread code will own the 'safe' objects given to it by the GUI; it won't have any interaction with the rest of the application.
  3. Unpack the result in the GUI: When the async operation is finished, it triggers an 'I am complete' event on the GUI thread. In response, the GUI thread can unpackage any results from the background operation and merge them back into the main business objects, safe in the knowledge that it won't be dealing with concurrent access.

我可以推荐 System.Threading.Tasks.Task 类作为上述大多数步骤的抽象.它是.NET 4.0中的新功能,但也可以单独下载.NET 3.5应用程序.

I can recommend the System.Threading.Tasks.Task class as an abstraction around most of the above steps. It's new in .NET 4.0, but it's also available as a separate download for .NET 3.5 apps.

步骤(1)和(2)是Task类的操作,无需进行任何定制.通过从后台线程内部生成单独的Task并指定

Steps (1) and (2) are what the Task class does without any customisation. You can achieve (3) by spawning a separate Task from inside the background thread and specifying TaskScheduler.FromCurrentSynchronizationContext as a scheduler. (You'll need to call FromCurrentSynchronizationContext from the GUI thread, in step (1), not from the background thread.)

这篇关于Winforms在没有InvokeRequired的情况下在多线程方案中将数据绑定到业务对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆