Domanda

Abbiamo una configurazione MSMQ coda che riceve messaggi e viene elaborato da un'applicazione. Ci piacerebbe avere un altro processo iscriviti alla coda e basta leggere il messaggio e la sua registrazione di contenuti.

Ho questo posto già, il problema è che è costantemente sbirciando la coda. CPU sul server quando questo è in esecuzione è di circa il 40%. Le piste Mqsvc.exe al 30% e questa applicazione funziona a 10%. Avrei preferito qualcosa che solo attende un messaggio di entrare, ottenere di notificato di esso, e quindi i registri senza costantemente il polling del server.

    Dim lastid As String
    Dim objQueue As MessageQueue
    Dim strQueueName As String

    Public Sub Main()
        objQueue = New MessageQueue(strQueueName, QueueAccessMode.SendAndReceive)
        Dim propertyFilter As New MessagePropertyFilter
        propertyFilter.ArrivedTime = True
        propertyFilter.Body = True
        propertyFilter.Id = True
        propertyFilter.LookupId = True
        objQueue.MessageReadPropertyFilter = propertyFilter
        objQueue.Formatter = New ActiveXMessageFormatter
        AddHandler objQueue.PeekCompleted, AddressOf MessageFound

        objQueue.BeginPeek()
    end main

    Public Sub MessageFound(ByVal s As Object, ByVal args As PeekCompletedEventArgs)

        Dim oQueue As MessageQueue
        Dim oMessage As Message

        ' Retrieve the queue from which the message originated
        oQueue = CType(s, MessageQueue)

            oMessage = oQueue.EndPeek(args.AsyncResult)
            If oMessage.LookupId <> lastid Then
                ' Process the message here
                lastid = oMessage.LookupId
                ' let's write it out
                log.write(oMessage)
            End If

        objQueue.BeginPeek()
    End Sub
È stato utile?

Soluzione

A Thread.Sleep (10) tra iterazioni peek può risparmiare un sacco di cicli.

L'unica altra opzione mi viene in mente è quello di costruire la registrazione in applicazione di lettura coda.

Altri suggerimenti

Hai provato a usare MSMQEvent.Arrived per tenere traccia dei messaggi?

  

L'evento Arrivato dell'oggetto MSMQEvent è sparato quando il metodo MSMQQueue.EnableNotification di un'istanza dell'oggetto MSMQQueue che rappresenta una coda aperta è stata chiamata e un messaggio viene trovato o arriva alla posizione di applicabile nella coda.

Non c'è API che vi permetterà di sbirciare ogni messaggio una sola volta.

Il problema è che BeginPeek esegue la sua richiamata immediatamente se c'è già un messaggio sulla coda. Dal momento che non sta rimuovendo il messaggio (questo è peek , dopo tutto, non ricevono!), Quando il callback inizia capolino di nuovo il processo ricomincia, quindi corre MessageFound quasi costantemente.

I tuoi migliori opzioni sono per registrare i messaggi nella scrittore o il lettore. diario lavorerà per brevi periodi (se vi interessa soltanto i messaggi ricevuti), ma non sono una soluzione a lungo termine:

  

Mentre il sovraccarico delle prestazioni di   il recupero dei messaggi da una coda che   è configurato per il journaling è solo   circa il 20% in più rispetto recupero   messaggi senza journal, il vero   costo è di problemi imprevisti causati   quando un incontrollato eseguito il servizio MSMQ   la memoria o la macchina è fuori   spazio su disco

Questo funziona per me. Si blocca il filo, mentre in attesa di un messaggio. Ogni controlli a ciclo ciclo del _bServiceRunning membro della classe per vedere se il filo deve interrompere.

    private void ProcessMessageQueue(MessageQueue taskQueue)
    {
        // Set the formatter to indicate body contains a binary message:
        taskQueue.Formatter = new BinaryMessageFormatter();

        // Specify to retrieve selected properties.
        MessagePropertyFilter myFilter = new MessagePropertyFilter();
        myFilter.SetAll();
        taskQueue.MessageReadPropertyFilter = myFilter;

        TimeSpan tsQueueReceiveTimeout = new TimeSpan(0, 0, 10); // 10 seconds

        // Monitor the MSMQ until the service is stopped:
        while (_bServiceRunning)
        {
            rxMessage = null;

            // Listen to the queue for the configured duration:
            try
            {
                // See if a message is available, and if so remove if from the queue if any required
                // web service is available:
                taskQueue.Peek(tsQueueReceiveTimeout);

                // If an IOTimeout was not thrown, there is a message in the queue
                // Get all the messages; this does not remove any messages
                Message[] arrMessages = taskQueue.GetAllMessages();

                // TODO: process the message objects here;
                //       they are copies of the messages in the queue
                //       Note that subsequent calls will return the same messages if they are
                //       still on the queue, so use some structure defined in an outer block
                //       to identify messages already processed.

            }
            catch (MessageQueueException mqe)
            {
                if (mqe.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
                {
                    // The peek message time-out has expired; there are no messages waiting in the queue
                    continue; // at "while (_bServiceRunning)"
                }
                else
                {
                    ErrorNotification.AppLogError("MSMQ Receive Failed for queue: " + mqs.Name, mqe);
                    break; // from "while (_bServiceRunning)"
                }
            }
            catch (Exception ex)
            {
                ErrorNotification.AppLogError("MSMQ Receive Failed for queue: " + mqs.Name, ex);
                break; // from "while (_bServiceRunning)"
            }
        }

    } // ProcessMessageQueue()

IMHO si dovrebbe basta accendere nel diario sulla coda. Poi si sono garantiti una copia è conservata di tutti i messaggi che sono stati commessi alla coda, e che proprio non è il caso con il tuo tentativo laborous per rendere il proprio meccanismo per registrare tutto.

Molto, molto più semplice e più affidabile è quello di accedere e rimuovere i messaggi inseriti nel journal in modo pianificato, se volete qualcosa di più facilmente leggibile rispetto alla coda stessa (e certamente vorrebbe che). Poi in realtà non importa quanto velocemente o no il processo sta funzionando, è sufficiente per ottenere i messaggi una volta, ed è nel complesso solo un modo molto migliore per risolvere il problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top