Mr. Smith
Mr. Smith

Reputation: 5558

C# - ThreadPool.QueueUserWorkItem() Requirements

I have a windows service that has a lot of work to do simultaneously. I've looked into threading and found the ThreadPool class. I'm currently stuck, it doesn't seem to have any effect, it's like whatever I'm queuing is never run or called. In the service's OnStart() event I create a thread like this:

Thread mainThread = new Thread(ReceiveMessages);
mainThread.Start();

Inside the method ReceiveMessages() I have a routine that checks a message queue and then iterates through the messages. For each iteration I call the following code to do some work with each message:

ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object state)
{
    Interpreter.InsertMessage(encoding.GetBytes(MessageBody));
}), null);

I think the syntax is right, it compiles with no issues, but I can't help but feel that I am missing something. When I run the service, nothing happens. However, if I replace the above code snippet with this:

insertThread = new Thread(delegate() { Interpreter.InsertMessage(encoding.GetBytes(MessageBody)); });
insertThread .Start();

It works 100%. It's not very efficient though and can cause the service to crash (which is does occasionally, the reason why I'm trying to use TheadPool instead). Can anyone shed some light on the subject?

Upvotes: 0

Views: 3239

Answers (2)

Jeff Sternal
Jeff Sternal

Reputation: 48583

It looks like you're creating a closure over MessageBody in your wait callback. If the caller's MessageBody property is null by the time the thread pool executes the work item, then that's what InsertMessage will operate on.

You need to define an overload of Interpreter.InsertMessage that accepts an object and use that as your WaitCallback:

public void InsertMessage(object messageBody) {
    this.InsertMessage((byte[])messageBody);
}

Then pass the message body bytes as the second parameter:

ThreadPool.QueueUserWorkItem(new WaitCallback(Interpreter.InsertMessage), 
                             encoding.GetBytes(MessageBody));

Upvotes: 2

Reed Copsey
Reed Copsey

Reputation: 564323

By default, when you create a new Thread, the thread is a Foreground thread. ThreadPool threads, however, have IsBackground set to true.

This means that a threadpool thread will not keep your application alive. This is probably why it's never "running" - it's just shutting down right away.

It's not very efficient though and can cause the service to crash (which is does occasionally, the reason why I'm trying to use TheadPool instead). Can anyone shed some light on the subject?

The self-constructed thread should be just as efficient (once the thread is up and running). The "crashing" will not be helped in any way by the ThreadPool thread - you'll still need to debug your service appropriately.

Upvotes: 1

Related Questions