0

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?

2 Answers 2

2

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));
Sign up to request clarification or add additional context in comments.

1 Comment

That is perfect! Works like a charm!
1

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.

3 Comments

I understand what you're saying. ReceiveMessages() has a while(true) loop that continually checks the message queue though, so every time there are messages, each message gets it's own thread to do some work. Perhaps that has some sort of effect?
@Mr. Smith: If the main thread terminates, you'll shut down the applciation (if you're using ThreadPool threads), since you need to have at least one non-background thread to keep it alive...
Yes, but isn't that what I'm doing in the OnStart() event? You said that creating a new Thread is by default a Foreground thread, wouldn't that make mainThread in my first code snippet above a thread that would keep it alive? I only utilize the ThreadPool inside that thread. What do you think?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.