根据Jason Dolinger视频,我创建了装饰正常模型的DispatchingWcfModel。但我不明白为什么需要它。我应该总是使用某种Dispatching模型吗?如果我使用普通模型而不是调度模型怎么办?为什么我需要“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 :(得分:1)
TL; DR: DispatchingWcfModel
类包装注入IWcfModel
并保证在新数据出现时 - 将以安全方式事件{{1}将更改分发到UI事件已在后台线程中引发,因此IWcfModel.DataArrived
始终使用Dispatcher将回调推送到UI线程。
更详细:在您的示例DispatchingWcfModel
类订阅注入DispatchingWcfModel
的事件,因此当事件被引发时 - 事件处理程序IWcfModel
将是调用和最重要的点 - 它会在实际引发事件的线程上被调用,因此调用线程可能不是UI线程,因此对UI控件的任何更改都将失败,避免使用Dispatched。
在WPF中,当您需要更新UI元素时,Dispatcher非常有用,因此应该在UI Thread中完成。正确的方法 - 将此工作委托给Dispatcher,Dispatcher持久化应该在UIThread上执行的工作项(请求)队列。
MSDN:
在WPF中,DispatcherObject只能由Dispatcher访问它 与....关联。例如,后台线程无法更新 与Dispatcher关联的Button的内容 UI线程。为了让后台线程访问内容 Button的属性,后台线程必须委托工作 到与UI线程关联的Dispatcher。这是完成的 通过使用Invoke或BeginInvoke。调用是同步的 BeginInvoke是异步的。该操作被添加到队列中 指定DispatcherPriority的Dispatcher。
答案 1 :(得分: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);
Dispatcher对于不同的消息优先级也有不同的队列,您可以指定一个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);
答案 2 :(得分:0)
调度程序用于访问图形用户元素。这些用户元素是在调度程序的行为中创建的。其他线程不允许访问它们。因此,当您想要访问gui元素时,您必须在调度程序上调用该操作。
但调度模型似乎是错误的方法。这些事情应该在视图模型中完成。这就是为什么有一个视图模型的原因。该模型通常是POCO或DTO,因此您不能依赖实现IWcfModel接口的每个模型。
我不知道您正在谈论的视频,但似乎作者对MVVM的理解有点偏僻。
答案 3 :(得分:0)
如果没有详细介绍(请点击此处的其他答案),请在
时使用Dispatcher没有。 2是多线程时的明显选择。当从后台线程调用时,必须将UI的更新移动或“编组”到UI线程。如果你不知道这意味着什么,请在这里做一点阅读,因为这是多线程开发新用户必须学习的最大障碍之一,这里有成千上万的相关问题。
没有。 1更加模糊,但可以归功于BeginInvoke
的重载值DispatcherPriority。
有时您在UI线程中工作,并且知道您想要更新UI,但您需要以后。示例包括可能需要等到用户完成键入的更新,以免按下下一个键消除UI更改。