MSMQ & Multithreading

M

Massimo

I'm writing a .NET (2.0) application than needs to receive messages from a
message queue and do some processing on them; the application is
multithreaded, and each thread runs in a loop receving a message, processing
it and so on; the loop is controlled by a flag, if this flag becomes to true
the thread exits.

To stop the application, the controller thread sets the flag to true and
calls Thread.Interrupt() on each thread... but this doesn't seem to stop the
thread if it's blocked on a MessageQueue.Receive() operation.

Why is this?
And how can I solve this problem?

Someone suggested using a two-part loop, having the thread sleep for a while
and then check the message queue with a short timeout; this way, the thread
can be interrupted. But this seems a lot inefficient to me.

Any ideas?

Thanks


Massimo
 
C

Carl Daniel [VC++ MVP]

Massimo said:
I'm writing a .NET (2.0) application than needs to receive messages from a
message queue and do some processing on them; the application is
multithreaded, and each thread runs in a loop receving a message,
processing it and so on; the loop is controlled by a flag, if this flag
becomes to true the thread exits.

To stop the application, the controller thread sets the flag to true and
calls Thread.Interrupt() on each thread... but this doesn't seem to stop
the thread if it's blocked on a MessageQueue.Receive() operation.

Why is this?

Apparently MessageQueue.Receive blocks outside the CLR. Thread.Interrupt
can only wake up a thread that's blocked inside the CLR.
And how can I solve this problem?

I would expect that simply closing the queue will cause those threads
blocked in reads to wake up with an error.
Someone suggested using a two-part loop, having the thread sleep for a
while and then check the message queue with a short timeout; this way, the
thread can be interrupted. But this seems a lot inefficient to me.

Another approach is rather than sleep, have the thread call one of the
overloads of Receive that takes a timeout. When a timeout occurs, check the
terminate flag and end the thread if appropriate.

Yes, this is somewhat inefficient, but it may be acceptable depending on
your particular needs.

All in all, you're probably better off re-architecting your solution. Have
a single thread call Receive (or BeginReceive) on the queue, and when it
gets a message pass it off to the thread pool for processing.

-cd
 
M

Massimo

Apparently MessageQueue.Receive blocks outside the CLR. Thread.Interrupt
can only wake up a thread that's blocked inside the CLR.

I was fearing something like that :-/
I would expect that simply closing the queue will cause those threads
blocked in reads to wake up with an error.

Will it disable and/or delete the queue itself? There's another application
sending messages to it, and it needs the queue even if this one stops.
Another approach is rather than sleep, have the thread call one of the
overloads of Receive that takes a timeout. When a timeout occurs, check
the terminate flag and end the thread if appropriate.

Yes, this is somewhat inefficient, but it may be acceptable depending on
your particular needs.

I'll probably do something like that; I just didn't want the threads to run
when there are no messages to process.
All in all, you're probably better off re-architecting your solution.
Have a single thread call Receive (or BeginReceive) on the queue, and when
it gets a message pass it off to the thread pool for processing.

That wouldn't solve the problem of stopping this single thread :)


Massimo
 
S

sloan

You have to make the .Receive or .Peek .. and use a TimeSpan period. (aka,
use the overloaded version of Receive or .Peek.

The TimeSpan for (the 2 items above) needs to be less....... then the
TimeSpan you use when you call the Thread.Interupt or Thread.Abort() (these
have a TimeSpan overload also)

...

Then, you have the catch the specific MSMQException, and the Timeout period.
Here is where you check your flag, and exit out.

You have to remember that msmq is COM stuff, and thus happens outside the
..Net world. Thus the Thread.Interupt or .Abort doesn't affect it as you
might think it would.
 
G

Guest

Another solution to this problem is to send a custom Quit message to the
message q then exit when this particular message is received.
 
E

EmeraldShield

Massimo said:
I'm writing a .NET (2.0) application than needs to receive messages from a
message queue and do some processing on them; the application is
multithreaded, and each thread runs in a loop receving a message,
processing it and so on; the loop is controlled by a flag, if this flag
becomes to true the thread exits.

To stop the application, the controller thread sets the flag to true and
calls Thread.Interrupt() on each thread... but this doesn't seem to stop
the thread if it's blocked on a MessageQueue.Receive() operation.

Why are you running threads like this?

If they are all processing the same queue why not use the AsyncReceive?
Then you get the benefit of when the app starts shutting down the Async
calls all come back with Errors that the Queue is closed.

You would not need to test for quit, just close the Queue and all the Async
operations will come back to their calling app.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top