Click here to Skip to main content
15,885,546 members
Articles / Desktop Programming / WPF

WPF: A Most Useful Threading Component

Rate me:
Please Sign up or sign in to vote.
4.97/5 (54 votes)
30 Dec 2009CPOL19 min read 121.3K   1.2K   147  
A threading component that shows failures/busy status and data.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;

namespace ThreadingComponent
{
    /// <summary>
    /// This ViewModel contains all the data required to run a work delegate
    /// (the TaskFunc Func<Dictionary<String,Object>,ThreadableItem<T>>) and also
    /// exposes methods to allow the work delegate to be run on a new thread. The 
    /// Data obtained by running the background thread is exposed on the Data
    /// property, and the BgWorker is also exposed as a property so that it can be
    /// used within Unit tests.
    /// </summary>
    /// <typeparam name="T">The return type of the threading operation</typeparam>
    public class ThreadableItemViewModel<T> : ThreadableItemViewModelBase
    {
        #region Data
        private ThreadableItem<T> data;
        private Func<Dictionary<String,Object>,ThreadableItem<T>> taskFunc;
        private BackgroundTaskManager<ThreadableItem<T>> bgWorker;
        private Dictionary<String, Object> parameters = null;
        #endregion

        #region Private Methods
        /// <summary>
        /// Sets up the actual BackgroundTaskManager<T> component
        /// </summary>
        private void SetupWorker()
        {
            if (taskFunc == null)
                throw new NullReferenceException("TaskFunc can not be null");

            bgWorker = new BackgroundTaskManager<ThreadableItem<T>>(
                 () =>
                 {
                     return taskFunc(Parameters);
                 },
                 (result) =>
                 {
                     Data = result;
                 });

            BgWorker.BackgroundTaskStarted -= BackgroundTaskStarted;
            BgWorker.BackgroundTaskCompleted -= BackgroundTaskCompleted;

            BgWorker.BackgroundTaskStarted += BackgroundTaskStarted;
            BgWorker.BackgroundTaskCompleted += BackgroundTaskCompleted;
        }

        /// <summary>
        /// Event that is raised when the background work is Completed. This event
        /// is raised by the internal BackgroundTaskManager<T> component
        /// </summary>
        private void BackgroundTaskCompleted(object sender, EventArgs args)
        {
            //The order that these properties IS IMPORTANT, as it dictates
            //which Adorner will be shown
            IsBusy = false;
            Failed = !String.IsNullOrEmpty(Data.Error);

        }

        /// <summary>
        /// Event that is raised when the background work is Started. This event
        /// is raised by the internal BackgroundTaskManager<T> component
        /// </summary>
        private void BackgroundTaskStarted(object sender, EventArgs args)
        {
            //The order that these properties IS IMPORTANT, as it dictates
            //which Adorner will be shown
            IsBusy = true;
            Failed = false;
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Run the work delegate on a new thread
        /// </summary>
        public void Run()
        {
            SetupWorker();
            bgWorker.RunBackgroundTask();
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// The actual work delegate. This must ALWAYS take a 
        /// Dictionary<String,Object> as the 1st parameter, which is the collection
        /// of parameters that the work delegate may need to do its work. This can obviously
        /// be null. The T is the expected return type for the threading operation
        /// </summary>
        public Func<Dictionary<String,Object>,ThreadableItem<T>> TaskFunc
        {
            set
            {
                taskFunc = value;
            }
        }

        /// <summary>
        /// A Dictionary of key/value pairs, where each pair is a parameter
        /// that the work delegate (TaskFunc) may need to do its work
        /// </summary>
        public Dictionary<String, Object> Parameters
        {
            get { return parameters; }
            set { parameters = value; }
        }

        /// <summary>
        /// The BackgroundTaskManager exposed so you can use it within
        /// Unit tests. See the actual <see cref="BackgroundTaskManager">
        /// BackgroundTaskManager</see> code for how to do that
        /// </summary>
        public BackgroundTaskManager<ThreadableItem<T>> BgWorker
        {
            get { return bgWorker; }
        }

        /// <summary>
        /// The actual Data that is the result of running the 
        /// background threading operation
        /// </summary>
        public ThreadableItem<T> Data
        {
            get { return data; }
            set
            {
                data = value;
                if (data != null)
                    this.ErrorMessage = data.Error;
                NotifyPropertyChanged("Data");
            }
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions