简体   繁体   English

我可以从辅助线程初始化ViewModel吗?

[英]Can I initialize ViewModel from a worker thread?

I am designing a WPF application following MVVM pattern. 我正在按照MVVM模式设计WPF应用程序。 But when it comes to multi-threading issue, I find my knowledge quite limited. 但是当涉及到多线程问题时,我发现我的知识非常有限。 My question is exactly like the title: can I create the ViewModel objects in a worker thread? 我的问题与标题完全一样:我可以在工作线程中创建ViewModel对象吗?

Currently we are not using any dependency injection so I just create the ViewModel object in the constructor of the View in UI thread (I guess it is not the best practice). 当前,我们没有使用任何依赖注入,因此我只是在UI线程中的View的构造函数中创建ViewModel对象(我认为这不是最佳实践)。 But now there is a problem: we have one core class, let's call it CoreContext , from our legacy software which is responsible for many core tasks, Data Access Layer between our SW and database is one of them. 但是现在出现了一个问题:我们有一个核心类,我们可以将其CoreContext ,它来自负责许多核心任务的旧版软件,软件与数据库之间的数据访问层就是其中之一。 Many of our ViewModel hold one reference to CoreContext as data member. 我们的许多ViewModel CoreContext一个对CoreContext引用作为数据成员。 Unfortunately this class is not built thread-safe. 不幸的是,该类不是线程安全的。 When I create the ViewModel instance(and hence the CoreContext instance) in UI thread, it is guaranteed that CoreContext is only accessed in the owning thread. 当我在UI线程中创建ViewModel实例(并因此创建CoreContext实例)时,可以确保仅在拥有线程中访问CoreContext However, when it involves with some heavy database query, the UI becomes not responsive. 但是,当它涉及一些繁重的数据库查询时,UI不会响应。

So now I am wondering, is it possible to instantiate the ViewModel (hence the CoreContext instance) in a non-UI thread so the UI can be responsive when the VM(ultimately the CoreContext ) is making heavy query? 所以现在我想知道,是否可以在非UI线程中实例化ViewModel (因此为CoreContext实例),以便在VM(最终为CoreContext )进行大量查询时UI可以响应?

I don't think it's a good idea to create and update the ViewModel on a non-UI thread. 我认为在非UI线程上创建和更新ViewModel不是一个好主意。 However, nothing actually prevents you from doing so, if you really have to. 但是,如果确实需要,实际上没有什么可以阻止您这样做。 You would just need to make the whole ViewModel thread-safe, ie, use proper locks everywhere you access the data fields, including property getter/setters. 您只需要使整个ViewModel线程安全的即可,即,在访问数据字段的任何地方都使用适当的锁,包括属性getter / setter。 That should be done for the whole ViewModel object hierarchy. 这应该在整个ViewModel对象层次结构中完成。

The WPF framework will automatically marshal INotifyPropertyChanged.PropertyChanged notifications for the data-bound UI controls (at least, in .NET 4.5, AFAIK). WPF框架将自动INotifyPropertyChanged.PropertyChanged数据绑定的UI控件的INotifyPropertyChanged.PropertyChanged通知(至少在.NET 4.5中为AFAIK)。 This way, the controls will be updating themselves automatically on the main UI thread, as expected. 这样,控件将按预期在主UI线程上自动更新自己。

What's important: if setting or getting any ViewModel property initiates a background operation involving your legacy Data Access Layer, you'd have to carry on such operation on the same thread your Data Access Layer was originally created on. 重要的是:如果设置或获取任何ViewModel属性会启动涉及旧数据访问层的后台操作,则您必须在最初创建数据访问层的同一线程上进行此类操作。 That is, implement thread affinity for it. 也就是说,为其实现线程关联。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM