Extended Threading: Do More with the Same Thread
This class is a wrapper around System.Threading.Thread

Introduction
This class I wrote could be classified as an experiment, because normally regular threads are more than enough to do whatever you need to do. Maybe it is best that I give a little background first.
I am currently working on a project where it is needed to monitor the performance of other computers.
Every time the computer to monitor has sent back its performance data, the function to get this data must be called again.
At first I did this in another thread that was created each time data was received. So I thought to myself: "Can't this be done in a more efficient way?", since creating threads is an expensive operation (and my old notebook is very slow).
The class I wrote is a wrapper around System.Threading.Thread
. It's purpose is to give you the possibility to execute a function in a different thread, and if you want to do this multiple times, you don't have to make a new thread every time. The advantage is that it performs much better (as making threads is an expensive operation) and is easy to use.
There are two ways of executing: once and then pause or keep executing and you can pause this at any time.
As an extra, there is the possibility to dispatch to the GUI. This is handy if you want to, for instance, change the text of a label on a form.
Background
If you are not familiar with threading in .NET and delegates, here is some documentation as provided by Microsoft:
Quick Overview of the Datamembers

Here you see the datamembers of the ExtendedThread
class. As you probably can derive, it implements the interface IDisposable
.
Using the Code
If you download the source, I think it will be clear enough to understand how it works. Still it is best that I summarize this:
- If you look at the code below, you will see that the
ExtendedThread
class is a wrapper around the regular thread. - It uses an inner thread that does the work. Functionality is added to be able to pause the thread.
- Functions without an argument (
ExtendedThreadDelegate
) and functions with an argument (ExtendedThreadArgumentDelegate
) can be executed as you can see in the constructors. - Two ways of executing are available:
ExecuteFunctionOnceThenPause ()
andExecuteFunctionAndKeepExecuting (int delayBetweenExecutions)
- Finally it is possible to dispatch to the GUI. This is handy if you want to, for instance, change the text of a label on a form.
Before going over the code in the ExtendedThread
class, I will first explain what the demo does.
The Demo
In the demo, you will see that you can compare ExtendedThread
with regular threading and the threadpool.
Click one of the buttons to try one of the three ways of executing on another thread. The Windows taskmanager shows the difference in CPU usage between them.
The function that is executed every 100 milliseconds is shown below:
private void ThreadStart(object o)
{
try
{
for (int i = 0; i < 9999; i++)
new Random(DateTime.Now.Millisecond).NextBytes(new byte[999]);
if ((o as string) == "DispatchToGui")
this.Text = "Times executed:" + (++_ul);
}
catch { }
}
This is what happens if you click the button to start an ExtendedThread
:
private void btnExtendedThread_Click(object sender, EventArgs e)
{
if (_t == null || _t.IsDisposed)
{
_t = new ExtendedThread(new ExtendedThreadArgumentDelegate(ThreadStart),
"argument");
//
//Try this for a demonstration of the dispatching to the Gui.
//_t = new ExtendedThread(new ExtendedThreadArgumentDelegate(ThreadStart),
"DispatchToGui", this);
//
}
if (!_t.IsExecutingFunction)
{
//Execute every 100 milliseconds.
_t.ExecuteFunctionAndKeepExecuting(100);
btnExtendedThread.Text = "Pause";
btnDispose.Enabled = true;
btnRegularThread.Enabled = false;
btnThreadpool.Enabled = false;
}
else
{
_t.Pause();
btnExtendedThread.Text = "Continue";
btnRegularThread.Enabled = true;
btnThreadpool.Enabled = true;
}
}
Inside the ExtendedThread Class
The Delegates
//The delegate for a function without arguments.
public delegate void ExtendedThreadDelegate();
//The delegate for a function with an argument.
public delegate void ExtendedThreadArgumentDelegate(object arg);
The Properties
//The thread used to execute the given function,
//this is kept alive until you want to stop it (Dispose () or Dispose (int timeout)).
//When a new object of ExtendedThreading.Thread is made,
//this thread is initiated without specific properties except that
//it is a background thread.
//You can set a few properties of this thread before executing the given function.
public Thread InnerThread
{
get { return _innerThread; }
}
//Gets if the function is being executed.
public bool IsExecutingFunction
{
get { return _executeFunction; }
}
//Gets if the inner thread is ready to execute the function.
public bool IsReadyToExecute
{
get { return _isReadyToExecute; }
}
public bool IsDisposed
{
get { return (_innerThread == null); }
}
Initializing and Disposing
//To execute a function without an argument.
public ExtendedThread(ExtendedThreadDelegate del)
{
Init(del, null, null);
}
//Use this constructor if you want to dispatch to the GUI,
//for instance if you want to change the text of a label on a form.
//ctrl is the control (form) you want to dispatch to.
public ExtendedThread(ExtendedThreadDelegate del, Control ctrl)
{
Init(del, null, ctrl);
}
//To execute a function with an argument.
public ExtendedThread(ExtendedThreadArgumentDelegate del, object arg)
{
if (arg == null)
throw new ArgumentNullException("arg");
Init(del, arg, null);
}
public ExtendedThread(ExtendedThreadArgumentDelegate del, object arg, Control ctrl)
{
if (arg == null)
throw new ArgumentNullException("arg");
Init(del, arg, ctrl);
}
private void Init(Delegate del, object arg, Control ctrl)
{
if (del == null)
throw new ArgumentNullException("del");
_del = del;
_arg = arg;
_ctrl = ctrl;
_innerThread = new Thread(ThreadStart);
//To make sure the inner thread is disposed when the application is closed.
_innerThread.IsBackground = true;
}
public void Dispose()
{
Dispose(0);
}
//timeout is the timeout in milliseconds to let the inner thread 'die'.
//If it is still alive after this timeout, it will be shutdown.
public void Dispose(int timeout)
{
if (!IsDisposed)
{
_isReadyToExecute = false;
if (timeout < 0)
timeout = 0;
//To let the loop end.
DateTime now = DateTime.Now;
double endTime = new TimeSpan(now.Day, now.Hour, now.Minute,
now.Second, now.Millisecond).TotalMilliseconds + timeout;
//The timeout could be a bit off, because of the calculation of the
//current total milliseconds.
//I could have used a partial timeout and let the thread sleep that
//partial timeout
//until there has been equally slept as the timeout given with this function
//or until the thread is not busy anymore,
//but I find this a bit messy.
while (_isInnerThreadBusy && new TimeSpan(DateTime.Now.Day, DateTime.Now.Hour,
DateTime.Now.Minute, DateTime.Now.Second,
DateTime.Now.Millisecond).TotalMilliseconds < endTime)
{ }
_executeFunction = false;
_isInnerThreadBusy = false;
_innerThread.Abort();
_innerThread = null;
}
}
Executing the Given Function
//The function will be executed once.
public void ExecuteFunctionOnceThenPause()
{
_keepExecuting = false;
//A minimum delay to keep the thread busy without pushing the CPU to 100%.
_delayBetweenExecutions = 1;
ExecuteFunction();
}
//The execution of the function stays in a loop until you pause.
//It is advised to set a delay larger then 0 milliseconds,
//otherwise there will be 100% CPU usage (ASAP execution of the function).
public void ExecuteFunctionAndKeepExecuting(int delayBetweenExecutions)
{
_keepExecuting = true;
_delayBetweenExecutions = delayBetweenExecutions;
if (_delayBetweenExecutions < 0)
_delayBetweenExecutions = 0;
ExecuteFunction();
}
private void ExecuteFunction()
{
if (IsDisposed)
throw new Exception("The inner thread was disposed.");
_executeFunction = true;
if (!_isReadyToExecute)
{
_isReadyToExecute = true;
_innerThread.Start();
}
}
//Pauses the execution of the function if using ExecuteFunctionAndKeepExecuting ().
public void Pause()
{
_keepExecuting = false;
}
private void ThreadStart()
{
_isInnerThreadBusy = true;
try
{
while (_isReadyToExecute)
{
if (_executeFunction)
{
_executeFunction = _keepExecuting;
if (_ctrl == null)
if (_arg == null)
(_del as ExtendedThreadDelegate).Invoke();
else
(_del as ExtendedThreadArgumentDelegate).Invoke(_arg);
else
DispatchToGui();
}
Thread.Sleep(_delayBetweenExecutions);
}
}
catch (Exception ex)
{
//Do not throw an exception while disposing.
if (_isReadyToExecute)
throw new Exception("The function you want to execute threw an exception.
\nPlease do your error handling inside that function.\n" + ex.Message);
_isReadyToExecute = false;
}
_executeFunction = false;
_isInnerThreadBusy = false;
}
//This is handy if you want to change something on the Gui, for instance:
//the text of a label on a form.
//This will only work if a handle for the control is created.
private void DispatchToGui()
{
if (_ctrl.IsHandleCreated)
{
try
{
if (_arg == null)
_ctrl.Invoke(_del);
else
_ctrl.Invoke(_del, _arg);
}
catch (Exception ex)
{
throw new Exception("Could not dispatch to the Gui.\n" + ex.Message);
}
}
else
{
throw new Exception("Please make sure a handle for the control (form)
is created before trying to dispatch to it.");
}
}
Points of Interest
I think I have covered everything. This is my first article, so any comments about improving it are very welcome.