2011-11-28 269 views
1

关注Jason Dolinger视频我已经装扮了装饰普通模型的DispatchingWcfModel。但我不明白为什么我需要它。我应该总是使用某种调度模式?如果我将使用普通模型而不是调度模型呢?为什么我需要“调度员”?何时在mvvm中使用Dispatcher?

class DispatchingWcfModel : IWcfModel 
{ 

    private readonly IWcfModel _underlying; 
    private readonly Dispatcher _currentDispatcher; 

    public DispatchingWcfModel(IWcfModel model) 
    { 
     _currentDispatcher = Dispatcher.CurrentDispatcher; 
     _underlying = model; 
     _underlying.DataArrived += _underlying_DataArrived; 
    } 

    private void _underlying_DataArrived(List<ConsoleData> obj) 
    { 
     Action dispatchAction =() => 
     { 
      if (DataArrived != null) 
      { 
       DataArrived(obj); 
      } 
     }; 
     _currentDispatcher.BeginInvoke(DispatcherPriority.DataBind, dispatchAction); 
    } 

    public List<ConsoleData> DataList 
    { 
     get { throw new NotImplementedException(); } 
     set { throw new NotImplementedException(); } 
    } 

    public event Action<List<ConsoleData>> DataArrived; 
} 
+0

我想你最好给Jason的视频添加一个链接。我想大多数人都没有看到它,并且可能没有考虑到他必须实现这样一个ViewModel的原因。现在对我来说(我没有看过视频)我认为这个ViewModel是没有意义的。 – Snowbear

+0

由于某种原因,此视频暂时无法使用,请点击此处http://blog.lab49.com/archives/2650 – javapowered

回答

1

TL; DR:DispatchingWcfModel类收官注入IWcfModel,并保证当一个新数据来源 - 的变化会出动安全的方式事件UI IWcfModel.DataArrived事件已经在后台线程已经提高,所以DispatchingWcfModel使用总是推回调调度程序到UI线程。

更详细:在您的例子DispatchingWcfModel类订阅到注射IWcfModel的事件,所以,当事件已经提升 - 事件处理程序_underlying_DataArrived将被称为什么最重要的一点 - 将它的线程上称为这实际上引发了一个事件,因此调用线程可能不会是UI线程,因此UI控件的任何更改都将失败,以避免使用Dispatched。

在您需要更新UI元素时,WPF Dispatcher非常有用,因此这应该在UI线程中完成。正确的做法 - 将这项工作委托给Dispatcher,它支持应该在UIThread上执行的工作项(请求)队列。

MSDN

在WPF中,一个DispatcherObject的只能由分派器它 访问相关联。例如,后台线程无法更新 与UI线程上的分派器关联的Button的内容。为了让后台线程访问Button的内容 属性,后台线程必须将工作 委托给与UI线程关联的分派器。这通过使用Invoke或BeginInvoke完成 。 Invoke是同步的,并且BeginInvoke是异步的。该操作被添加到指定的DispatcherPriority的Dispatcher的队列 中。

+0

仍然不清楚。如果某人将某种操作添加到“DataArrived”而不是UI-具体。那么UI线程将用于非UI工作。此外,它不清楚如何确定我是否更新UI ...我认为,如果我更新ViewModel - 这意味着我正在更新UI,因为UI监听ViewModel中的更改。另外我不明白为什么这个人http://msdn.microsoft.com/en-us/magazine/dd419663.aspx不使用“调度器”。使用'Dispatcher'不是强制性的? – javapowered

+0

从MVVM的角度来看,我并不清楚为什么Model(DispatchingWcfModel)知道诸如将更改推送到UI线程之类的东西,这应该由ViewModel完成。这在UI线程中执行一些代码块并不是问题,因为默认情况下,在主线程中执行的所有应用程序代码都是UI线程 – sll

+0

模型,只是通知任何感兴趣的相关方,新数据已到达而没有其他内容。只有模型知道数据何时更新... – javapowered

0

调度程序用于访问图形用户元素。这些用户元素是在调度程序的行为中创建的。其他线程不允许访问它们。所以当你想访问gui元素时,你必须调用调度器上的操作。

但是调度模型似乎是错误的方法。这些东西应该在视图模型中完成。这就是为什么有一个视图模型的原因。该模型通常是POCO或DTO,因此不能依赖实现IWcfModel接口的每个模型。

我不知道你在谈论的视频,但似乎作者对MVVM的理解有点偏离标准。

1

Dispatcher是WPF的主UI线程的内部消息队列。它可以在后台线程中使用,以在应用程序的主UI线程上运行命令。

这很重要,因为WPF不允许您访问在其他线程上创建的对象。例如,如果在主UI线程上创建了Button,则不能从另一个线程修改该按钮,但可以使用另一个线程的Dispatcher向主UI线程发送命令来更新该按钮。

这适用于所有对象,而不仅仅是UI元素。如果在一个线程上创建了类似ObservableCollection的内容,则另一个线程无法修改它。正因为如此,所有对象通常都是在主UI线程上创建的。

调度程序消息可以同步或异步处理。例如,

// Will execute SomeMethod on the main UI thread synchronously 
Dispatcher.Invoke(SomeMethod); 

// Will execute SomeMethod on the main UI thread asynchronously 
Dispatcher.BeginInvoke(SomeMethod); 

的调度员也有消息不同优先级的不同队列,你可以用你的消息使一些在指定时间运行指定DispatcherPriority

// Will execute SomeMethod on the main UI thread synchronously, 
// at the same priority as Rendering controls 
Dispatcher.Invoke(DispatcherPriority.Render, SomeMethod); 

// Will execute SomeMethod on the main UI thread asynchronously, 
// at the same priority as background processes 
Dispatcher.BeginInvoke(DispatcherPriority.Background, SomeMethod); 
0

没有进入太多的技术细节(给予好评这里其他的答案),您可以使用调度时

  1. 你希望做一些事情以后
  2. 你希望做一些UI线程

当多线程处理时,第2号显然是非常明智的选择。当从后台线程调用UI时,UI的更新必须移动或“编组”到UI线程。如果您不知道这意味着什么,请在此处阅读一下,因为这是新开发的多线程开发人员必须学习的最大障碍之一,在这里可以找到成千上万的相关问题。

第1号稍微模糊一点,但可能要归功于BeginInvoke的超负荷值,它们的值为DispatcherPriority

可以有时间当你在UI线程做的工作,你知道你想更新UI,但你需要做的。例子包括可能需要等待用户完成输入的更新,以免按下下一个按键消除UI更改。

相关问题