.NET Framework Bookmark and Share   
 index > Common Language Runtime > rate this code please
 

rate this code please

Following is a custom thread pool class thatI attempted to write. Would you please take a look at the code and see what design issues (or coding ) issues does it have?

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;


namespace Gemini.Threading.ThreadPool
{
public delegate void CallBackHandler(object context);
public sealed class CustomThreadPool : IDisposable
{
#region private memebers...
private readonly int _CurrentPoolCount;
private List<ThreadData> _Threads = new List<ThreadData>();
private ManualResetEvent _ItemsInQueueEvent = new ManualResetEvent(false);
private SynchQueue _QueueWorkList;

private static void OnThreadStart(object o)
{
try
{
ThreadData data = (ThreadData)o;
Interlocked.Exchange(ref data._InUse, 0);
data._startedEvent.Set();
SynchQueue pendingQueue = data._PendingQueue;
Console.WriteLine(" ThreadPool[tid:{0}]thread started", Thread.CurrentThread.ManagedThreadId);

while (true)
{
int eventIndex = WaitHandle.WaitAny(new WaitHandle[] { data._startEvent, data._QueueState });
Interlocked.Exchange(ref data._InUse, 1);
CallBackHandler callbk = null;
object context = null;
if (eventIndex == 1)
{
QueueData qdata = pendingQueue.DeQueue();
if (qdata == null)
{
continue;
}
DebugOutput(qdata);
callbk = qdata._Callback;
context = qdata._Context;
}
else if (eventIndex == 0)
{
Console.WriteLine("ThreadPool[tid{0}]:: processing the non-queued work", Thread.CurrentThread.ManagedThreadId);
callbk = data._callback;
context = data._Context;
}
else throw new Exception("Unknown Error");

if (callbk != null)
{
callbk(context);
}
else throw new ArgumentException("No callback specified");

Interlocked.Exchange(ref data._InUse, 0);
}
}
catch (ThreadAbortException){}
}

private static void DebugOutput(QueueData qdata)
{
TimeSpan tm = DateTime.Now - qdata.dtEnqueuedTime;
string time = "";
if (tm.Days > 0)
time += tm.Days.ToString() + "days ";
if (tm.Hours > 0)
time += tm.Hours.ToString() + "hrs ";
if (tm.Minutes > 0)
time += tm.Minutes.ToString() + "mins ";
if (tm.Seconds > 0)
time += tm.Seconds.ToString() + "secs ";
if (tm.Milliseconds > 0)
time += tm.Milliseconds.ToString() + "ms ";
Console.WriteLine("ThreadPool[tid:{0}]::Processing Queued Worked after : {1}", Thread.CurrentThread.ManagedThreadId, time);
}
#endregion

#region public methods

public CustomThreadPool(int count)
{
_CurrentPoolCount = count;
_QueueWorkList = new SynchQueue(_ItemsInQueueEvent);
//initialize a fixed number of threads....
for (int i = 0; i < _CurrentPoolCount; ++i)
{
ThreadData dt = new ThreadData(_ItemsInQueueEvent, _QueueWorkList);
_Threads.Add(dt);
WaitHandle.WaitAll(new WaitHandle[] { dt._startedEvent });
}

}
public void Dispose()
{
foreach (ThreadData td in _Threads)
{
td.Dispose();
}
}

// processes the data either immediately or queues up the data...
// returns true: if data is queued up, otherwise false
public bool Process(CallBackHandler workcallback, object context)
{
foreach (ThreadData data in _Threads)
{
if (Interlocked.CompareExchange(ref data._InUse, 1, 0) == 0)
{
//Interlocked.Exchange...
data._callback = workcallback;
data._Context = context;
data._startEvent.Set();
return false;
}
}
//else we need to queue the call in the queue and as soon as a thread becomes ready we need to pick next
//item from the queue.
//no idle thread found , queue the data...
_QueueWorkList.Enqueue(new QueueData(workcallback, context));
return true;
}
#endregion

#region internal classes...
internal sealed class ThreadData
{
internal CallBackHandler _callback;
internal Thread _Thread;
internal int _InUse;
internal object _Context;
internal AutoResetEvent _startedEvent = new AutoResetEvent(false);
internal ManualResetEvent _QueueState;
internal SynchQueue _PendingQueue;
internal AutoResetEvent _startEvent = new AutoResetEvent(false);

internal void Dispose()
{
if (_Thread != null)
{
_Thread.Abort();
_Thread.Join();
}
}
internal ThreadData(ManualResetEvent qs, SynchQueue sq)
{
_PendingQueue = sq;
_QueueState = qs;
_InUse = 0;
_Thread = new Thread(new ParameterizedThreadStart(CustomThreadPool.OnThreadStart));
_Thread.Start(this);

}

}
internal sealed class QueueData
{
internal DateTime dtEnqueuedTime;
internal DateTime dtDequeuedTime;
internal CallBackHandler _Callback;
internal object _Context;
internal QueueData(CallBackHandler cb, object o)
{
_Callback = cb;
_Context = o;
}
}
internal class SynchQueue
{
private Queue<QueueData> _QueuedCallBacks = new Queue<QueueData>();
private ManualResetEvent _QueueState;

internal SynchQueue(ManualResetEvent handle)
{
_QueueState = handle;
}
internal void Enqueue(QueueData qd)
{
lock (this)
{
qd.dtEnqueuedTime = DateTime.Now;

_QueuedCallBacks.Enqueue(qd);
_QueueState.Set();
}
}
internal QueueData DeQueue()
{
lock (this)
{
QueueData data = null;
if (_QueuedCallBacks.Count == 0)
_QueueState.Reset();
else
data = _QueuedCallBacks.Dequeue();
return data;
}
}
}
#endregion
}
}

:::usuage:

public static void Main(string [] args){

Gemini.Threading.ThreadPool.CustomThreadPool tp = new Gemini.Threading.ThreadPool.CustomThreadPool(iThreadCount);
for (int i = 0; i < iCallCount; ++i)
{
tp.Process(new CallBackHandler(OnCallback), null);
}
}
static void OnCallback(object o) {
Console.WriteLine("do some work here");
}

CSharpProgrammer

Before the code can be rated you need to tell us what problem you are trying to solve that the built in System.Threading.ThreadPool does not, and whether this code does in fact solve that problem.

It could be the best written code in the world, but if it does not solve the problem it needs to then it is poor; you may have created the best pair of sunglasses in the world but they are no use if the problem is that it is raining.

Greg Beech

Before the code can be rated you need to tell us what problem you are trying to solve that the built in System.Threading.ThreadPool does not, and whether this code does in fact solve that problem.

It could be the best written code in the world, but if it does not solve the problem it needs to then it is poor; you may have created the best pair of sunglasses in the world but they are no use if the problem is that it is raining.

Greg Beech
I am trying to write some code and see what others think of the quality of the code.
I am not trying to replace the .NET Thread pool
CSharpProgrammer
Code is the end result of many other things. There is no absolute rating since many factors do need to be considered. Looking at your code you would miss my review because of

- Missing fn function code comments
- Missing function documentation
- Missing good tracing at least for debug builds to make it maintanable
- Missing unit tests
- What requirements does your code fullfull? If there are no documented goals then it is not possible to validate that your code does what it is supposed to do.

Yours,
Alois Kraus

Alois

You can use google to search for other answers

Custom Search

More Threads

• CryptDeriveKey give different results WinXP and Win2K
• Cryptography - I'm new to it and confused!
• MFC exe Crashes with /clr option
• Why does typeof(System.UIntPtr).IsPrimitive return 'true'?
• User Role (on Vista)
• Capture screenshot of entire desktop - multiple monitors
• System.DirectortServices
• MultiThreading Efficiency Question
• Management Object how to capture stderr
• PInvoke questions