Home All Groups Group Topic Archive Search About

MSMQ & Multithreading

Author
6 Oct 2006 10:23 PM
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

Author
6 Oct 2006 10:33 PM
Carl Daniel [VC++ MVP]
"Massimo" <bar***@mclink.it> wrote in message
news:uICiVYZ6GHA.3952@TK2MSFTNGP04.phx.gbl...
> 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
Author
6 Oct 2006 11:38 PM
Massimo
"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam>
ha scritto nel messaggio news:eBrmwdZ6GHA.2120@TK2MSFTNGP03.phx.gbl...

> 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 :-/

>> 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.

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
Author
9 Oct 2006 2:50 PM
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.







Show quote
"Massimo" <bar***@mclink.it> wrote in message
news:uICiVYZ6GHA.3952@TK2MSFTNGP04.phx.gbl...
> 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
>
Author
27 Dec 2006 1:16 AM
Patrick
Another solution to this problem is to send a custom Quit message to the
message q then exit when this particular message is received.

Show quote
"Massimo" wrote:

> 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
>
>
Author
3 Jan 2007 5:27 PM
EmeraldShield
"Massimo" <bar***@mclink.it> wrote in message
news:uICiVYZ6GHA.3952@TK2MSFTNGP04.phx.gbl...
> 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.

AddThis Social Bookmark Button