Frage

Wir haben ein MSMQ Queue-Setup, das von einer Anwendung verarbeitet Nachrichten und empfängt. Wir möchten, dass ein anderer Prozess in die Queue abonniert haben und nur die Nachricht lesen und den Inhalt anmelden.

ich dies bereits an der richtigen Stelle, ist das Problem, das es ständig ist die Warteschlange späht. CPU auf dem Server, wenn dieser ausgeführt wird, um 40%. Die mqsvc.exe läuft bei 30% und diese App läuft bei 10%. Ich würde lieber etwas, dass nur wartet auf eine Nachricht kommen, erhalten die davon benachrichtigt, und meldet sich dann, ohne dass der Server ständig Polling.

    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
War es hilfreich?

Lösung

Ein Thread.Sleep (10) zwischen Peek Iterationen können Sie eine Reihe von Zyklen speichern.

Die einzige andere Option, die ich denken kann, ist die Protokollierung in die Warteschlange Lese Anwendung zu erstellen.

Andere Tipps

Haben Sie versucht mit MSMQEvent.Arrived , um die Nachrichten zu verfolgen?

angekommenen Ereignis des MSMQEvent Objekts ausgelöst wird, wenn die MSMQQueue.EnableNotification Methode einer Instanz des Objekts MSMQQueue eine offene Warteschlange darstellt aufgerufen wurde und eine Nachricht gefunden wird oder kommt an der jeweiligen Position in der Warteschlange.

Es gibt keine API, die Sie bei jeder Nachricht nur einmal spähen lassen.

Das Problem ist, dass BeginPeek seinen Rückruf ausführt sofort, wenn es bereits eine Meldung in der Warteschlange. Da Sie die Nachricht nicht entfernen möchte (dies ist Peek schließlich nicht erhalten!), Wenn der Rückruf späht beginnt wieder der Prozess beginnt von vorne, so MessageFound läuft fast ständig.

Ihre besten Optionen sind die Nachrichten in dem Schreiber oder dem Leser zu protokollieren. Journaling wird für eine kurze Zeit arbeiten (wenn Sie nur über Nachrichten kümmern, die empfangen werden), aber keine langfristige Lösung:

Während die Performance-Overhead von Abrufen von Nachrichten aus einer Warteschlange, die nur für Journale konfiguriert ist etwa 20% mehr als retrieving Nachrichten ohne Journaling, das reale Kosten sind unerwartete Probleme verursacht wenn eine ungeprüfte MSMQ-Dienst läuft aus dem Speicher oder die Maschine ist aus Speicherplatz

Das funktioniert für mich. Es blockiert den Faden, während für eine Nachricht wartet. Jede Schleife Zyklus prüft die Klasse Mitglied _bServiceRunning, um zu sehen, wenn der Thread abbrechen sollte.

    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 sollten Sie nur einschalten in der Warteschlange Journaling. Dann werden Sie eine Kopie garantieren alle Nachrichten gehalten, die an die Warteschlange begangen worden waren, und das ist einfach nicht der Fall mit Ihrem laborous Versuch Ihren eigenen Mechanismus zu machen, alles zu protokollieren.

Viel, viel einfacher und zuverlässiger ist die Journaling-Nachrichten nach einem Zeitplan zu protokollieren und entfernen, wenn Sie etwas leichter lesbar als die Warteschlange wollen selbst (und das würde ich auf jeden Fall will). Dann spielt es keine Rolle, wie schnell oder nicht der Prozess funktioniert, müssen Sie nur einmal die Nachrichten erhalten, und es ist insgesamt nur eine viel bessere Möglichkeit, das Problem zu lösen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top