异步WPF命令 [英] Asynchronous WPF Commands

查看:133
本文介绍了异步WPF命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:在code在这个问题的一部分 deSleeper ,如果你想完整的源代码。

Note: The code in this question is part of deSleeper if you want the full source.

一个我想了命令的事情是烤设计异步操作。我想pssed禁用,而命令被执行,回来时完成按钮$ P $。我想在一个线程池工作项目执行的实际工作。最后,我想一个办法来处理异步处理过程中发生任何错误。

One of the things I wanted out of commands was a baked design for asynchronous operations. I wanted the button pressed to disable while the command was executing, and come back when complete. I wanted the actual work to be performed in a ThreadPool work item. And lastly, I wanted a way to handle any errors that occurred during the asynchronous processing.

我的解决方案是一个AsyncCommand:

My solution was an AsyncCommand:

public abstract class AsyncCommand : ICommand
{
	public event EventHandler CanExecuteChanged;
	public event EventHandler ExecutionStarting;
	public event EventHandler<AsyncCommandCompleteEventArgs> ExecutionComplete;

	public abstract string Text { get; }
	private bool _isExecuting;
	public bool IsExecuting
	{
		get { return _isExecuting; }
		private set
		{
			_isExecuting = value;
			if (CanExecuteChanged != null)
				CanExecuteChanged(this, EventArgs.Empty);
		}
	}

	protected abstract void OnExecute(object parameter);

	public void Execute(object parameter)
	{	
		try
		{
			IsExecuting = true;
			if (ExecutionStarting != null)
				ExecutionStarting(this, EventArgs.Empty);

			var dispatcher = Dispatcher.CurrentDispatcher;
			ThreadPool.QueueUserWorkItem(
				obj =>
				{
					try
					{
						OnExecute(parameter);
						if (ExecutionComplete != null)
							dispatcher.Invoke(DispatcherPriority.Normal, 
								ExecutionComplete, this, 
								new AsyncCommandCompleteEventArgs(null));
					}
					catch (Exception ex)
					{
						if (ExecutionComplete != null)
							dispatcher.Invoke(DispatcherPriority.Normal, 
								ExecutionComplete, this, 
								new AsyncCommandCompleteEventArgs(ex));
					}
					finally
					{
						dispatcher.Invoke(DispatcherPriority.Normal, 
							new Action(() => IsExecuting = false));
					}
				});
		}
		catch (Exception ex)
		{
			IsExecuting = false;
			if (ExecutionComplete != null)
				ExecutionComplete(this, new AsyncCommandCompleteEventArgs(ex));
		}
	}

	public virtual bool CanExecute(object parameter)
	{
		return !IsExecuting;
	}
}

这样的问题是:这一切必要吗?我注意到内置的异步支持数据绑定,那么为什么不执行命令?也许是有关参数的问题,这是我的下一个问题。

so the question is: Is all this necessary? I've noticed built in asynchronous support for data-binding, so why not command execution? Perhaps it's related to the parameter question, which is my next question.

推荐答案

我已经能够原始样品向下细化,并有一些建议任何人都遇到了类似的情况。

I've been able to refine the original sample down and have some advice for anyone else running into similar situations.

首先,考虑是否BackgroundWorker的将满足需求。我现在还在用AsyncCommand往往能得到自动禁用功能,但如果很多事情可以和BackgroundWorker的完成。

First, consider if BackgroundWorker will meet the needs. I still use AsyncCommand often to get the automatic disable function, but if many things could be done with BackgroundWorker.

但通过包装BackgroundWorker的,AsyncCommand提供了命令一样的功能与异步行为(我也有一个的关于这个话题博客条目)

But by wrapping BackgroundWorker, AsyncCommand provides command like functionality with asynchronous behavior (I also have a blog entry on this topic)

public abstract class AsyncCommand : ICommand
{
	public event EventHandler CanExecuteChanged;
	public event EventHandler RunWorkerStarting;
	public event RunWorkerCompletedEventHandler RunWorkerCompleted;

	public abstract string Text { get; }
	private bool _isExecuting;
	public bool IsExecuting
	{
		get { return _isExecuting; }
		private set
		{
			_isExecuting = value;
			if (CanExecuteChanged != null)
				CanExecuteChanged(this, EventArgs.Empty);
		}
	}

	protected abstract void OnExecute(object parameter);

	public void Execute(object parameter)
	{	
		try
		{	
			onRunWorkerStarting();

			var worker = new BackgroundWorker();
			worker.DoWork += ((sender, e) => OnExecute(e.Argument));
			worker.RunWorkerCompleted += ((sender, e) => onRunWorkerCompleted(e));
			worker.RunWorkerAsync(parameter);
		}
		catch (Exception ex)
		{
			onRunWorkerCompleted(new RunWorkerCompletedEventArgs(null, ex, true));
		}
	}

	private void onRunWorkerStarting()
	{
		IsExecuting = true;
		if (RunWorkerStarting != null)
			RunWorkerStarting(this, EventArgs.Empty);
	}

	private void onRunWorkerCompleted(RunWorkerCompletedEventArgs e)
	{
		IsExecuting = false;
		if (RunWorkerCompleted != null)
			RunWorkerCompleted(this, e);
	}

	public virtual bool CanExecute(object parameter)
	{
		return !IsExecuting;
	}
}

这篇关于异步WPF命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆