现在我们在搭建好的MVVM架构中实现Dispatcher:
我们把之前作成的CustomizeDispatcher放入PresenterBase中调用,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace HarlyApp.BaseFiles
{
public class PresenterBase<T>
{
public IView<T> view { get; set; }
private ICommand _cancelCommand;
public ICommand CancelCommand
{
get
{
if (_cancelCommand == null)
{
_cancelCommand = new RelayCommand(() => this.CloseWindow());
}
return _cancelCommand;
}
}
public PresenterBase(IView<T> view)
{
this.view = view;
this.Initialize();
}
public void ShowDialog()
{
this.view.ShowWindow();
}
protected virtual void Initialize()
{ }
public void CloseWindow()
{
this.view.CloseWindow();
}
public List<Exception> exceptionList = new List<Exception>();
public bool CustomizeDispatcher(Action<bool> callbackAction, params Action[] actions)
{
Func<bool> function = new Func<bool>
(() =>
{
ParallelLoopResult result = Parallel.For(0, actions.Length,
(int ac, ParallelLoopState state) =>
{
try
{
actions[ac].Invoke();
}
catch (Exception ex)
{
exceptionList.Add(ex);
}
});
return !exceptionList.Any();
});
callbackAction.Invoke(function.Invoke());
return !exceptionList.Any();
}
}
}
后台我这边用了最简单的entityFramework并写了个get方法进行调用,
我们用Classes,Components,GamePlans这3个集合作为Itemsource进行绑定
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HarlyApp.BaseFiles;
using System.Windows.Input;
using System.Windows;
using DataBaseEntity;
using System.Collections.ObjectModel;
namespace HarlyApp
{
public class MainWindowPresenter : PresenterBase<MainWindow>
{
public DataRepository dataaccess = new DataRepository();
private ICommand _displayCommand;
public ICommand DisplayCommand
{
get
{
if (_displayCommand == null)
{
_displayCommand = new RelayCommand(() => this.Display());
}
return _displayCommand;
}
}
public ObservableCollection<ACL_CLASS> Classes { get; set; }
public ObservableCollection<SR_COMPONENT> Components { get; set; }
public ObservableCollection<SR_GAMEPLAN> GamePlans { get; set; }
public MainWindowPresenter(IView<MainWindow> view)
: base(view)
{
this.view.DataContext = this;
}
StringBuilder sb = new StringBuilder();
protected override void Initialize()
{
this.Classes = new ObservableCollection<ACL_CLASS>();
this.Components = new ObservableCollection<SR_COMPONENT>();
this.GamePlans = new ObservableCollection<SR_GAMEPLAN>();
}
public void Display()
{
this.CustomizeDispatcher(
complete =>
{
if (complete)
MessageBox.Show("Complete");
else
MessageBox.Show("Failed");
},
() =>
{
this.dataaccess.GetItems<ACL_CLASS>().ToList().ForEach(c=>this.Classes.Add(c));
},
() =>
{
this.dataaccess.GetItems<SR_COMPONENT>().ToList().ForEach(c=>this.Components.Add(c));
},
() =>
{
this.dataaccess.GetItems<SR_GAMEPLAN>().ToList().ForEach(c=>this.GamePlans.Add(c));
});
}
}
}
看似很正常的source,但是跑的结果确实Failed,看了下结果其实是ObserverableCollection集合的问题,这个集合不支持异步调用以及集合修改,这个问题网上有好多了,直接把解决方法贴在下面:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
namespace HarlyApp.BaseFiles
{
public class AsyncObservableCollection<T> : ObservableCollection<T>
{
//获取当前线程的SynchronizationContext对象
private SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
public AsyncObservableCollection() { }
public AsyncObservableCollection(IEnumerable<T> list) : base(list) { }
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
//如果操作发生在同一个线程中,不需要进行跨线程执行
RaiseCollectionChanged(e);
}
else
{
//如果不是发生在同一个线程中
//准确说来,这里是在一个非UI线程中,需要进行UI的更新所进行的操作
_synchronizationContext.Post(RaiseCollectionChanged, e);
}
}
private void RaiseCollectionChanged(object param)
{
// 执行
base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the PropertyChanged event on the current thread
RaisePropertyChanged(e);
}
else
{
// Post the PropertyChanged event on the creator thread
_synchronizationContext.Post(RaisePropertyChanged, e);
}
}
private void RaisePropertyChanged(object param)
{
// We are in the creator thread, call the base implementation directly
base.OnPropertyChanged((PropertyChangedEventArgs)param);
}
}
}
我们把ObservarableCollection集合换成AsyncObservableCollection后,结果是出来了,初步设想得到了实现,不过还需要进行进一步测试以及优化,我们会在下一节来看看结果。