Asynchronous WPF Command

The ICommand interface provides a nice way of binding WPF buttons to methods in a view model. If those methods use any amount of time, though, you'll want to run them in a background thread.

This implementation of ICommand is an easily-extendable way to run methods in an async manner when a button is clicked. The base class creates a BackgroundWorker that runs a proxy for the Execute method. All you have to do is override OnExecute.

The

BeforeExecute

method allows you to run operations on the UI thread immediately before the BackgroundWorker does its async operation.

The

AfterExecute

method allows you to run operations after the BackgroundWorker completes its work. It also provides the Exception object (if one was thrown) that was thrown in the background thread.

/// <summary>
/// Implementation of <c>ICommand</c> that allows for asynchronous operation.
/// </summary>
public class AsyncCommandBase : ICommand
{
    /// <summary>
    /// Raises the <c>CanExecuteChanged</c> event for the command.
    /// </summary>
    /// <remarks>This method should be invoked whenever the returned value of <c>CanExecute</c> changes.</remarks>
    protected void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null) CanExecuteChanged(this, new EventArgs());
    }
 
    /// <summary>
    /// When overridden in a derived class, performs operations in the UI thread
    /// before beginning the background operation.
    /// </summary>
    /// <param name="parameter">The parameter passed to the <c>Execute</c> method of the command.</param>
    protected virtual void BeforeExecute(object parameter) { }
 
    /// <summary>
    /// When overridden in a derived class, performs operations in a background
    /// thread when the <c>Execute</c> method is invoked.
    /// </summary>
    /// <param name="parameter">The paramter passed to the <c>Execute</c> method of the command.</param>
    protected virtual void OnExecute(object parameter) { }
 
    /// <summary>
    /// When overridden in a derived class, performs operations when the
    /// background execution has completed.
    /// </summary>
    /// <param name="parameter">The parameter passed to the <c>Execute</c> method of the command.</param>
    /// <param name="error">The error object that was thrown during the background operation, or null if no error was thrown.</param>
    protected virtual void AfterExecute(object parameter, Exception error) { }
 
    /// <summary>
    /// Occurs when changes occur that affect whether or not the command should execute.
    /// </summary>
    public event EventHandler CanExecuteChanged;
 
 
    /// <summary>
    /// When overridden in a derived class, defines the method that determines whether the command can execute in its
    /// current state.
    /// </summary>
    /// <param name="parameter">
    /// Data used by the command. If the command does not require data to be passed,
    /// this object can be set to null.
    /// </param>
    /// <returns>True if this command can be executed; otherwise, false.</returns>
    public virtual bool CanExecute(object parameter)
    {
        return true;
    }
 
    /// <summary>
    /// Runs the command method in a background thread.
    /// </summary>
    /// <param name="parameter">
    /// Data used by the command. If the command does not require data to be passed,
    /// this object can be set to null.
    /// </param>
    public void Execute(object parameter)
    {
        BeforeExecute(parameter);
 
        var bgw = new BackgroundWorker();
 
        bgw.DoWork += (s, e) =>
        {
            OnExecute(parameter);
        };
        bgw.RunWorkerCompleted += (s, e) =>
        {
            AfterExecute(parameter, e.Error);
        };
        bgw.RunWorkerAsync();
    }
}

No comments for 'Asynchronous WPF Command'

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • Image links with 'rel="lightbox"' in the <a> tag will appear in a Lightbox when clicked on.

More information about formatting options

CAPTCHA
Please verify your species.