简体   繁体   English

NotificationObject的调度程序

[英]a dispatcher for NotificationObject

I have 2 NotificationObject objects that act as view models. 我有2个NotificationObject对象作为视图模型。 First NotificationObject contains properties that are binded to the view of a specific control, and second NotificationObject has some code that executes in another thread using Thread object. First NotificationObject包含绑定到特定控件视图的属性,第二个NotificationObject包含一些使用Thread对象在另一个线程中执行的代码。 I need to change properties of first NotificationObject from the running code of the second NotificationObject. 我需要从第二个NotificationObject的运行代码更改第一个NotificationObject的属性。 When I try to do it I get an exception "The calling thread cannot access this object because a different thread owns it.". 当我尝试这样做时,我得到一个异常“调用线程无法访问此对象,因为另一个线程拥有它。”

I think that I need to use some sort of dispatcher to access those properties as I would do in Windows Forms or classic WPF, but I can't find how to do it in Prism MVVM. 我认为我需要使用某种调度程序来访问这些属性,就像在Windows窗体或经典WPF中那样,但是我无法在Prism MVVM中找到它。 So how do I change the properties of first NotificationObject? 那么如何更改第一个NotificationObject的属性?

I am guessing that you have something created on one thread, and are trying to update it from the other thread, and WPF doesn't allow this. 我猜你在一个线程上创建了一些东西,并试图从另一个线程更新它,而WPF不允许这样做。 Objects can only be modified from the thread they were created on. 只能从创建它们的线程修改对象。

Usually all objects are created on the main UI thread, and the Dispatcher is used to pass asynchronous messages to the UI thread to update these objects. 通常,所有对象都在主UI线程上创建,Dispatcher用于将异步消息传递给UI线程以更新这些对象。 Any heavy processing can still be done on the background thread, however to update the property of an object you need to use the main UI thread. 任何繁重的处理仍然可以在后台线程上完成,但是要更新您需要使用主UI线程的对象的属性。

For example, something that looks like this would work: 例如,看起来像这样的东西会起作用:

MyNotificationObject obj = new MyNotificationObject;
obj.Items = MethodThatRunsOnBackgroundThread();

List<SomeObject> MethodThatRunsOnBackgroundThread()
{
    var list = new List<SomeObject>();
    // Do Work
    Return list;
}

While this will not: 虽然这不会:

MyNotificationObject obj = new MyNotificationObject;
MethodThatRunsOnBackgroundThread(obj);

void MethodThatRunsOnBackgroundThread()
{
    var list = new List<SomeObject>();
    // Do Work

    // This won't work since obj was created on UI thread
    obj.Items = List<SomeObject>;
}

Here is another example that works, because it is sending the message to update the object to the UI thread which created the object. 这是另一个有效的示例,因为它正在发送消息以将对象更新为创建对象的UI线程。

MyNotificationObject obj = new MyNotificationObject;
MethodThatRunsOnBackgroundThread(obj);

void MethodThatRunsOnBackgroundThread()
{
    var list = new List<SomeObject>();

    // Load List

    Application.Current.Dispatcher.BeginInvoke(DispatherPriority.Background,
        new Action(delegate { 
            obj.Items = list;
        }));
}

Application.Current.Dispatcher is pretty much the easiest solution.. Application.Current.Dispatcher是最简单的解决方案..

In .NET 4.5 this will thankfully not be necessary anymore. 在.NET 4.5中,幸运的是,这将不再是必要的。

Had to look for the Dispatcher in view's UserControl object, not in the model view's NotificationObject. 必须在视图的UserControl对象中查找Dispatcher,而不是在模型视图的NotificationObject中查找。 I think that it is not good to reference views from model views in MVVM, but I haven't found a better solution yet. 我认为从MVVM中的模型视图引用视图并不好,但我还没有找到更好的解决方案。

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

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