基于WPF的Dispatcher应用及探讨(三)

现在我们在搭建好的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后,结果是出来了,初步设想得到了实现,不过还需要进行进一步测试以及优化,我们会在下一节来看看结果。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值