I’m in needed of a thread worker in my .NET application – .NET has several classes such as thread pools etc., but I can’t find anything that runs on a single thread, which is a requirement in my case.
So I’ve had a go a writing one myself, but these things are notoriously tricky, I’m sure I’ve got something wrong. Can anyone improve it or point me in the direction of somthing similar that’s already been written?
public class ThreadWorker : IDisposable
{
public ThreadWorker()
{
m_Thread = new Thread(ThreadMain);
m_Thread.IsBackground = true;
m_Thread.Name = "Worker Thread";
m_Thread.Start();
}
public void Dispose()
{
if (!m_Terminate)
{
m_Terminate = true;
m_Event.Set();
m_Thread.Join();
}
}
public void QueueUserWorkItem(Action<object> callback, object data)
{
lock (m_Queue) m_Queue.Enqueue(new WorkItem(callback, data));
m_Event.Set();
}
void ThreadMain()
{
while (!m_Terminate)
{
if (m_Queue.Count > 0)
{
WorkItem workItem;
lock (m_Queue) workItem = m_Queue.Dequeue();
workItem.Callback(workItem.Data);
}
else
{
m_Event.WaitOne();
}
}
}
class WorkItem
{
public WorkItem(Action<object> callback, object data)
{
Callback = callback;
Data = data;
}
public Action<object> Callback;
public object Data;
}
AutoResetEvent m_Event = new AutoResetEvent(false);
Queue<WorkItem> m_Queue = new Queue<WorkItem>();
Thread m_Thread;
bool m_Terminate;
}
C’mon, Tear it apart!
PLEASE STOP ASKING WHETHER I NEED THIS: Yes I do – I have legacy C code that isn’t thread-safe, so I need to synchronise all of my calls to it on a background thread.
EDIT: Last minute change to my code was obviously incorrect ,fixed it.
I’m going to ignore the question of whether or not you should be doing this and just give you feedback about your code. Most are style issues or suggestions to use best practices, but others are bugs that need to be fixed.
m_Terminate. Or at the very least it needs to be volatile.Why are you usingFixedAction<object>and then passing null as a parameter? Can’t you just use ThreadStart if you don’t want a parameter?callbacktoQueueUserWorkItemis not null to avoidNullReferenceExceptionin the loop inThreadMain(fail fast).ObjectDisposedExceptionifQueueUserWorkItemis called afterDisposehas already been called.