我为什么要避免使用Dispatcher?

DHN*_*DHN 7 data-binding silverlight wpf

我已经阅读了很多关于绑定和GUI控件的线程亲和性的帖子,文章等.有些帖子中人们不想使用Dispatcher.

我还有一个同事避免在他的代码中使用Dispatcher.我问他原因,但他的回答并不能让我满意.他说,他不喜欢隐藏在课堂上的这种"魔法".

好吧,我是下一堂课的粉丝.


public class BindingBase : INotifyPropertyChanged
{
   public event PropertyChangedEventHandler PropertyChanged;

   private Dispatcher Dispatcher
   {
#if SILVERLIGHT
      get { return Deployment.Current.Dispatcher; }
#else
      get { return Application.Current.Dispatcher; }
#endif
   }

   protected void RaisePropertyChanged<T>(Expression<Func<T>> expr)
   {
      var memberExpr = (MemberExpression)expr.Body;
      string property = memberExpr.Member.Name;

      var propertyChanged = PropertyChanged;
      if (propertyChanged == null) return;

      if (Dispatcher.CheckAccess())
         propertyChanged.Invoke(this, new PropertyChangedEventArgs(property));
      else
         Dispatcher.BeginInvoke(() => RaisePropertyChanged(expr));
   }
}
Run Code Online (Sandbox Code Playgroud)

这是个问题.有些人不想使用这样的课程有什么理由吗?也许我必须重新考虑这种方法.

你必须承认,有一件奇怪的事情.Dispatcher.CheckAccess()被Intellisense排除在外.由于这个事实,也许他们有点可怕.

问候

编辑:

好的,另一个例子.考虑一个复杂的对象.作为例子的集合可能不是最好的主意.


public class ExampleVm : BindingBase
{
   private BigFatObject _someData;
   public BigFatObject SomeData
   {
      get { return _someData; }
      set
      {
         _someData = value;
         RaisePropertyChanged(() => SomeData);
      }
   }

   public ExampleVm()
   {
      new Action(LoadSomeData).BeginInvoke(null, null); //I know - it's quick and dirty
   }

   private void LoadSomeData()
   {
      // loading some data from somewhere ...
      // result is of type BigFatObject

      SomeData = result; // This would not work without the Dispatcher, would it?
   }
}
Run Code Online (Sandbox Code Playgroud)

Pav*_*kov 5

我个人也不反对Dispatcher视图模型类.我没有看到任何重大问题,但它为您的代码提供了最大的灵活性.

但我喜欢Dispatcher尽可能地封装基础设施代码中的用法.就像你使用RaisePropertyChanged方法一样(BTW,如果RaisePropertyChanged你不需要发送任何东西 - 绑定已经为你做了;你只需要对集合发送更改).

我在这里看到的最大和唯一的缺点是单元测试.当您尝试测试涉及使用的逻辑时,事情会变得棘手Dispatcher.想象一下,如果你在视图模型中有这样的代码:

private void UpdateMyCollection() 
{
   IList<ModelData> dataItems = DataService.GetItems();

   // Update data on UI
   Dispatcher.BeginInvoke(new Action(() => {
      foreach (ModelData dataItem in dataItems)
      {
         MyObservableCollection.Add(new DataItemViewModel(dataItem));
      }
   }));
}
Run Code Online (Sandbox Code Playgroud)

当从非UI线程更新集合时,这种代码非常典型.现在,您将如何编写单元测试来测试向可观察集合添加项目的逻辑?首先,你需要模拟Dispatcher属性,因为Application.Currentnull单元测试执行过程.第二,你将如何嘲笑它?你会创建一个模拟UI线程并使用该线程的特殊Dispatcher线程吗?所以,这种事情.

最重要的是,如果你希望你的代码对单元测试友好,你需要考虑如何模拟它Dispatcher.这是唯一的问题.

更新:

你提供的第二个例子将无需工作Dispatcher(绑定将起作用).