Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

WPF: A Most Useful Threading Component

, 30 Dec 2009 CPOL
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)

Share

About the Author

Sacha Barber
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 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

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.150327.1 | Last Updated 30 Dec 2009
Article Copyright 2009 by Sacha Barber
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid