博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转]异步command的实现
阅读量:5032 次
发布时间:2019-06-12

本文共 6931 字,大约阅读时间需要 23 分钟。

在WPF中,有时有些重操作,需要异步完成,来避免Ui锁死。

MVVM模式下,可以通过来实现此过程。

首先定义一个IAsyncCommand ,实现ICommand:

public interface IAsyncCommand : ICommand    {        Task ExecuteAsync(object parameter);    }

然后实现一个实现该接口的抽象Base:

public abstract class AsyncCommandBase : IAsyncCommand    {        public abstract bool CanExecute(object parameter);        public abstract Task ExecuteAsync(object parameter);        public async void Execute(object parameter)        {            await ExecuteAsync(parameter);        }        public event EventHandler CanExecuteChanged        {            add { CommandManager.RequerySuggested += value; }            remove { CommandManager.RequerySuggested -= value; }        }        protected void RaiseCanExecuteChanged()        {            CommandManager.InvalidateRequerySuggested();        }    }
AsyncCommandBase

再实现上述抽象类:

public class AsyncCommand
: AsyncCommandBase, INotifyPropertyChanged { private readonly Func
> _command; private readonly CancelAsyncCommand _cancelCommand; private NotifyTaskCompletion
_execution; public AsyncCommand(Func
> command) { _command = command; _cancelCommand = new CancelAsyncCommand(); } public override bool CanExecute(object parameter) { return Execution == null || Execution.IsCompleted; } public override async Task ExecuteAsync(object parameter) { _cancelCommand.NotifyCommandStarting(); Execution = new NotifyTaskCompletion
(_command(_cancelCommand.Token)); RaiseCanExecuteChanged(); await Execution.TaskCompletion; _cancelCommand.NotifyCommandFinished(); RaiseCanExecuteChanged(); } public ICommand CancelCommand { get { return _cancelCommand; } } public NotifyTaskCompletion
Execution { get { return _execution; } private set { _execution = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } private sealed class CancelAsyncCommand : ICommand { private CancellationTokenSource _cts = new CancellationTokenSource(); private bool _commandExecuting; public CancellationToken Token { get { return _cts.Token; } } public void NotifyCommandStarting() { _commandExecuting = true; if (!_cts.IsCancellationRequested) return; _cts = new CancellationTokenSource(); RaiseCanExecuteChanged(); } public void NotifyCommandFinished() { _commandExecuting = false; RaiseCanExecuteChanged(); } bool ICommand.CanExecute(object parameter) { return _commandExecuting && !_cts.IsCancellationRequested; } void ICommand.Execute(object parameter) { _cts.Cancel(); RaiseCanExecuteChanged(); } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } private void RaiseCanExecuteChanged() { CommandManager.InvalidateRequerySuggested(); } } } public static class AsyncCommand { public static AsyncCommand
Create(Func
command) { return new AsyncCommand
(async _ => { await command(); return null; }); } public static AsyncCommand
Create
(Func
> command) { return new AsyncCommand
(_ => command()); } public static AsyncCommand
Create(Func
command) { return new AsyncCommand
(async token => { await command(token); return null; }); } public static AsyncCommand
Create
(Func
> command) { return new AsyncCommand
(command); } }
AsyncCommand

其中的NotifyTaskCompletion实现了任务结束通知:

public sealed class NotifyTaskCompletion
: INotifyPropertyChanged { public NotifyTaskCompletion(Task
task) { Task = task; TaskCompletion = WatchTaskAsync(task); } private async Task WatchTaskAsync(Task task) { try { await task; } catch { } var propertyChanged = PropertyChanged; if (propertyChanged == null) return; propertyChanged(this, new PropertyChangedEventArgs("Status")); propertyChanged(this, new PropertyChangedEventArgs("IsCompleted")); propertyChanged(this, new PropertyChangedEventArgs("IsNotCompleted")); if (task.IsCanceled) { propertyChanged(this, new PropertyChangedEventArgs("IsCanceled")); } else if (task.IsFaulted) { propertyChanged(this, new PropertyChangedEventArgs("IsFaulted")); propertyChanged(this, new PropertyChangedEventArgs("Exception")); propertyChanged(this, new PropertyChangedEventArgs("InnerException")); propertyChanged(this, new PropertyChangedEventArgs("ErrorMessage")); } else { propertyChanged(this, new PropertyChangedEventArgs("IsSuccessfullyCompleted")); propertyChanged(this, new PropertyChangedEventArgs("Result")); } } public Task
Task { get; private set; } public Task TaskCompletion { get; private set; } public TResult Result { get { return (Task.Status == TaskStatus.RanToCompletion) ? Task.Result : default(TResult); } } public TaskStatus Status { get { return Task.Status; } } public bool IsCompleted { get { return Task.IsCompleted; } } public bool IsNotCompleted { get { return !Task.IsCompleted; } } public bool IsSuccessfullyCompleted { get { return Task.Status == TaskStatus.RanToCompletion; } } public bool IsCanceled { get { return Task.IsCanceled; } } public bool IsFaulted { get { return Task.IsFaulted; } } public AggregateException Exception { get { return Task.Exception; } } public Exception InnerException { get { return (Exception == null) ? null : Exception.InnerException; } } public string ErrorMessage { get { return (InnerException == null) ? null : InnerException.Message; } } public event PropertyChangedEventHandler PropertyChanged; }
NotifyTaskCompletion

假设为一个Button绑定一个IAsyncCommand,这个Button对应的命令就可以异步执行,而不锁死UI了。

 

※在原文章的代码中NotifyTaskCompletion实现有个,下载下来的代码是修复过的。千万别复制文章中的实现~

转载于:https://www.cnblogs.com/zhuyc110/p/5210829.html

你可能感兴趣的文章
IO流之File类
查看>>
sql 基础语句
查看>>
CF717A Festival Organization(第一类斯特林数,斐波那契数列)
查看>>
oracle直接读写ms sqlserver数据库(二)配置透明网关
查看>>
控件发布:div2dropdownlist(div模拟dropdownlist控件)
查看>>
Oracle composite index column ordering
查看>>
ActiveReports 报表控件官方中文入门教程 (3)-如何选择页面报表和区域报表
查看>>
kaggle竞赛
查看>>
区块链入门教程
查看>>
域 搭建OU 组织单元
查看>>
npm常用命令
查看>>
南海区行政审批管理系统接口规范v0.3(规划)4.2.【queryExpireList】当天到期业务查询...
查看>>
[置顶] 细说Cookies
查看>>
[wp7软件]wp7~~新闻资讯,阅读软件下载大全! 集合贴~~~
查看>>
生成指定位数随机数的方法
查看>>
java的垃圾回收
查看>>
Essential C++学习笔记
查看>>
python+selenium进行简单验证码获取
查看>>
where,having与 group by连用的区别
查看>>
【MySQL】MySQL锁和隔离级别浅析二 之 INSERT
查看>>