Question

I have a Winform C# Desktop application. It calls my web service, which in turn handles my upload request and puts it into a MSMQ.

At the moment, I am using a basic Winform C# app (installed on my server) to read from this queue and save my byte arrays to .jpegs.

Here is that code:

public Form1()
{
    InitializeComponent();
    string MotionMSMQ = ConfigurationManager.AppSettings["MotionMSMQ"].ToString();
    msgQ = new MessageQueue(MotionMSMQ);
}

Thread _th = null;
MessageQueue _msgQ = null;
private void btnStart_Click(object sender, EventArgs e) {
    try {
        lblStatus.Text = "started";
        _th = new Thread(Worker);
        _th.Start();
    } catch { }
}


private void Worker() {
    while (true) {
        try {
            if (_msgQ.CanRead) {                       
                System.Messaging.Message msgLog = _msgQ.Receive();
                using (MemoryStream ms = new MemoryStream()) {
                    Bitmap newMotionFrame = null;
                    try {
                        msgLog.BodyStream.CopyTo(ms);
                        byte[] msg = ms.ToArray();
                        //save to stream/jpeg 
                    } catch (Exception processError) {
                      //handle error
                    } finally {
                        if (newMotionFrame != null) {
                            newMotionFrame.Dispose();
                        }
                    }
                }
            }
        }
    }
}

I am mindful of infinite loops however. Is this the only/best way to continuously read from a MSMQ?

Était-ce utile?

La solution

An infinite loop is OK, if it doesn't uses all the CPU for nothing, and is used in an application (or a thread) that only does one task (such as a Windows service or a specific background thread that read/writes to a queue).

For the specific case of the message queue reading, I would suggest using MessageQueue.Receive that accepts a timeout as parameter. It's a blocking call (until a message is available in the queue OR the timeout is reached) that won't consume the CPU. You will have to catch the exception that'll be thrown when the timeout is reached.

Example:

MessageQueue messageQueue = ...;
TimeSpan queueReceiveTimeout = ...;

while (true)
{
    try
    {
        Message message = messageQueue.Receive(queueReceiveTimeout);
        ...
    }
    catch (MessageQueueException msmqEx)
    { 
        if (msmqEx.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
        {
            // Exception handling exceptionally used for normal code flow
            // Swallow the exception here
        }
        else
        {
            throw;
        }
    }
}

You could then use a condition in the while to stop your service properly (example: while (!this.isServiceStopping)) with a relatively small timeout (for example 5s), so your service/thread can be stopped properly within a maximum of 5 seconds.

Autres conseils

Use MSMQ Triggers which does the waiting for you and calls your app on message arrival.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top