C# 在UI线程之外使用依赖项对象的最佳实践

C# 在UI线程之外使用依赖项对象的最佳实践,c#,wpf,multithreading,dependencyobject,C#,Wpf,Multithreading,Dependencyobject,正如标题所示,我发现自己在这种情况下相当多,并且相信自己做错了什么。我经常希望UI能够根据后台任务的工作不断更新,但发现很难找到简单地尝试更新UI和在UI线程上工作之间的分离 假设我有一个简单的DependencyObject: public class TaskItem : DependencyObject { public string Name {get;set;} public string Command {get;set;} public WorkState

正如标题所示,我发现自己在这种情况下相当多,并且相信自己做错了什么。我经常希望UI能够根据后台任务的工作不断更新,但发现很难找到简单地尝试更新UI和在UI线程上工作之间的分离

假设我有一个简单的DependencyObject:

public class TaskItem : DependencyObject
{
    public string Name {get;set;}
    public string Command {get;set;}

    public WorkState State
    {
        get { return (WorkState)GetValue(StateProperty); }
        set { SetValue(StateProperty, value); }
    }

    public static readonly DependencyProperty StateProperty = 
        DependencyProperty.Register("State", typeof(WorkState), 
                                     typeof(TaskItem));
}
这些对象存储在称为mTaskItems的ObservableCollection中。在某些用户事件中,我想对以下对象执行一些操作:

Task.Run(new Action( () => 
{
   foreach (TaskItem task_item in mTaskItems.Where(n => n.State != 
                                                    WorkState.Executing))
   {
      DoSomeWork(task_item);
   }
}));
我无法检查上面示例中TaskItem的DependencyProperty状态,因为它现在位于拥有它的另一个线程上

如果您希望在处理过程中更新UI,那么在整个业务逻辑中散布调度程序是正常的,还是我的做法完全错误


我的依赖项对象是否应该根本不作为业务数据容器使用,而是作为UI数据容器存在?(如果是这样,连接它们的最佳设计是什么?)

谢谢

我发现自己处于这种情况下,相信自己做错了什么


我也相信。您无需在业务模型中扩展
DependencyObject
类。。。几乎没有任何共同的需要来扩展这个类
DependencyObject
s和
DependencyProperty
s设计用于UI对象。您可以通过在模型中实现来获得相同的属性通知功能

如果您希望在处理过程中更新UI,那么在整个业务逻辑中散布调度程序是正常的,还是我的做法完全错误


现在我要说的正是你应该做的。。。长时间运行的任务应该发生在后台线程中,当您需要更新UI时,您需要使用
调度程序

依赖对象
不应该是业务逻辑的一部分。DP应该用于视图中的数据绑定、动画等。好的,在某个时候,我的业务逻辑需要更新DPs,这将涉及dispatchers或其他设计。你知道最好的选择是什么吗?“我的依赖项对象根本不应该被用作业务数据容器吗?”没错!这种架构模式称为MVVM。您通常仅在视图中具有依赖项属性。正如您在case DependencyObjects中提到的,应该通过与这些对象关联的Dispatcher进行更新。这是唯一的办法。正如克莱门斯所建议的,MVVM是一种可行的方法。您应该绑定到ViewModel。视图中可见的内容(无论它们是否为依赖项对象)将自动更新。ViewModel还负责在对模型进行更改时重新查询模型。例如,如果UI中有一个“更新”,它将流入ViewModel,此时ViewModel需要足够智能,以获取任何数据,这些数据将根据它当前的操作进行更新。“当你需要更新UI时,你需要使用一个调度程序”——这是不正确的,至少在显式使用它方面是不正确的。假设采用“正常”实现,即使用
INotifyPropertyChanged
,WPF将自动将属性更改通知发送回UI线程。您只需从任何线程更新属性即可;绑定将在UI线程中更新绑定到它的UI对象。