Multithreading seems to be a hot topic of discussion for a lot of programmers. It also seems to be one of the more difficult concepts to grasp (or even to get started with). Luckily in C#/.Net it's pretty simple when compared to some other languages that I've dealt with. In C# all you need to do is make a call to ThreadPool or create a Thread class and you're done... Sort of anyway... However there is a lack of certain functionality that you may want to add. In my case I needed a way of being notified of certain events so I created a helper base class that is reusable.
/// <summary>
/// Worker class used in multi threading
/// </summary>
/// <typeparam name="ResultType">Result type</typeparam>
/// <typeparam name="InputParams">The input parameter type</typeparam>
public abstract class Worker<ResultType,InputParams>
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
/// <param name="Params">Parameters used in the function</param>
protected Worker(InputParams Params)
{
this.Params = Params;
this.WorkerThread = new Thread(DoWork);
}
#endregion
#region Protected Abstract Functions
/// <summary>
/// Function that actually does the work
/// </summary>
/// <param name="Params">Parameter used by the function</param>
/// <returns>The result of the function</returns>
protected abstract ResultType Work(InputParams Params);
#endregion
#region Public Functions
/// <summary>
/// Starts the thread
/// </summary>
public void Start()
{
this.WorkerThread.Start();
}
/// <summary>
/// Stops the thread and waits for it to finish
/// </summary>
public void Stop()
{
if (WorkerThread != null && WorkerThread.IsAlive)
{
this.WorkerThread.Join();
this.WorkerThread = null;
}
OnEndEventArgs EndEvents = new OnEndEventArgs();
EndEvents.Content = Result;
EventHelper.Raise<OnEndEventArgs>(Finished, this, EndEvents);
}
#endregion
#region Private Functions
/// <summary>
/// Wrapper for the function that actually does the work.
/// Calls the start and finished events as well as stores
/// the result for use within the class.
/// </summary>
private void DoWork()
{
EventHelper.Raise<OnStartEventArgs>(Started, this, new OnStartEventArgs());
Result = Work(this.Params);
OnEndEventArgs EndEvents = new OnEndEventArgs();
EndEvents.Content = Result;
EventHelper.Raise<OnEndEventArgs>(Finished, this, EndEvents);
}
#endregion
#region Events
/// <summary>
/// Called when the thread is finished
/// </summary>
public EventHandler<OnEndEventArgs> Finished { get; set; }
/// <summary>
/// Called when the thread is started
/// </summary>
public EventHandler<OnStartEventArgs> Started { get; set; }
/// <summary>
/// Can be used by the worker function to indicate progress
/// </summary>
public EventHandler<ChangedEventArgs> Updated { get; set; }
/// <summary>
/// Can be used by the worker function to indicate an exception has occurred
/// </summary>
public EventHandler<OnErrorEventArgs> Exception { get; set; }
#endregion
#region Properties
/// <summary>
/// Indicates whether or not the thread is stopped/started
/// </summary>
public bool Stopped
{
get
{
if (WorkerThread != null && WorkerThread.IsAlive)
return false;
return true;
}
}
/// <summary>
/// The result (can be used by the class that inherits from this base class
/// </summary>
protected ResultType Result { get; set; }
/// <summary>
/// Parameters used in the function
/// </summary>
private InputParams Params = default(InputParams);
/// <summary>
/// The thread used
/// </summary>
private Thread WorkerThread=null;
#endregion
}
The code should be fairly easy to follow. You use this as a base class adding the result and parameter type. There is one function that you need to override. That's it really, well with one exception. The class has events that it uses (which uses EventArgs that are within my utility library). It has Started and Finished which is called when the thread is started and stopped respectively. The Finished event will contain the results from the function within the Content object.There are also events for Updated and Exception which are optional. The Updated event would be used to update the rest of the world on the thread's progress. The Exception event on the other hand would be used when the thread has an exception, letting everyone else know. Anyway, I hope that the code can be of use to someone. So try it out, leave feedback, and happy coding.
1c407d64-575d-4093-97c1-4ad1babd8e80|2|5.0