-
Notifications
You must be signed in to change notification settings - Fork 0
Threads
Threads are complex, and Rhino Commons is here to try to help. The library contains several interesting classes with regards to threads: RhinoThreadPool
, ThreadSafeQueue
, CountdownLatch
The RhinoThreadPool
allows you to:
- Cancel pending work or abort executing threads safely
- Wait for work in the thread pool to be completed
- Events for starting and finishing work items
Basic usage is similar to the usual thread pool:
RhinoThreadPool.QueueUserWorkItem(new WaitCallback(MyCallback), myState);
But once you started on that, you can do more interesting things with it.
WorkItem workItem = RhinoThreadPool.QueueUserWorkItem(new WaitCallback(MyCallback), myState);
// at a later time
workItem.Cancelled = true;//will prevent it from running if it is not already running
// or this, which allows you to get its state
WorkItemStatus status = RhinoThreadPool.Cancel(workItem, false);
// and optionally abort the work item execution if needed
WorkItemStatus status = RhinoThreadPool.Cancel(workItem, true);
You can also register work and wait for it:
for(int i=0;i<100;i++)
{
RhinoThreadPool.QueueUserWorkItem(new WaitCallback(Foo), i);
}
RhinoThreadPool.WaitForAllThreadsToFinish();
When work item begins to run:
RhinoThreadPool.WorkStarted += delegate(WorkItem item)
{
Console.WriteLine(item.State+" started");
}
When work item finishes to run, including abnormally:
RhinoThreadPool.WorkFinished += delegate(WorkItem item)
{
Console.WriteLine(item.State+" started");
}
Important: RhinoThreadPool
doesn't try to catch exceptions, if a user work item callback has thrown an exception, it will be propagate to the default .NET handling of unhandled thread exception, and will usually terminate the application.
As the name implies, it allows to Enqueue()
and Dequeue()
in a thread safe manner. Trying to Dequeue from an empty queue will block, until there is data to return. To call the queue without blocking, use TryDequeue()
A simple lock implementation that allows a producer to wait for a set of consumer to finish their work, here is a simple test that demonstrate its usage:
[Test]
public void WaitForEventToRun()
{
int count = 5000;
CountdownLatch countdown = new CountdownLatch(count);
bool[">count">](https://web.archive.org/web/20120619180408/http://ayende.com/wiki/Rhino+Commons+-+Threads.ashx%5d+done+%3d+new+bool%5bcount.ashx "] done = new bool<a class=") done = new bool\[count;
for (int i = 0; i < count; i++)
{
int j = i;
ThreadPool.QueueUserWorkItem(delegate
{
done[j](https://web.archive.org/web/20120619180408/http://ayende.com/wiki/Rhino+Commons+-+Threads.ashxj.ashx "j") = true;
countdown.Set();
});
}
bool result = countdown.WaitOne();
Assert.IsTrue(result);
for (int i = 0; i < count; i++)
{
Assert.IsTrue(done[i](https://web.archive.org/web/20120619180408/http://ayende.com/wiki/Rhino+Commons+-+Threads.ashxi.ashx "i"), "{0} was not set to true", i);
}
}