Pregunta

Tenemos una configuración de cola de MSMQ que recibe mensajes y es procesada por una aplicación. Nos gustaría tener otro proceso suscribirse a la cola y que acaba de leer el mensaje y ingrese su contenido.

Tengo esto en el lugar ya, el problema es que es constantemente asomando la cola. CPU en el servidor cuando este está en funcionamiento es de alrededor de 40%. Las carreras Mqsvc.exe en 30% y esta aplicación funciona a 10%. Yo prefiero tener algo que sólo espera un mensaje a entrar, para conseguir de notificado de la misma, y ??luego lo registra sin estar constantemente sondeando el servidor.

    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
¿Fue útil?

Solución

A Thread.Sleep (10) en entre iteraciones ojeada puede ahorrar un montón de ciclos.

La única otra opción que se me ocurre es la construcción de la tala en la aplicación de lectura de cola.

Otros consejos

¿Ha intentado utilizar MSMQEvent.Arrived para realizar un seguimiento de los mensajes?

El evento Llegado del objeto MSMQEvent se activa cuando el método MSMQQueue.EnableNotification de una instancia del objeto MSMQQueue que representa una cola abierta ha sido llamada y un mensaje se encuentra o llega a la posición de aplicación en la cola.

No hay API que le permitirá vistazo a cada mensaje una sola vez.

El problema es que BeginPeek ejecuta su devolución de llamada de inmediato si ya hay un mensaje en la cola. Puesto que no se está eliminando el mensaje (esto es peek , después de todo, no recibirá!), Cuando su devolución de llamada empieza asomando de nuevo el proceso comienza de nuevo, por lo que se ejecuta MessageFound casi constantemente.

Sus mejores opciones son para registrar los mensajes en el escritor o el lector. el diario funcionará por períodos cortos (si sólo se preocupan por los mensajes que se reciben), pero no son una solución a largo plazo:

Mientras que la sobrecarga de rendimiento de la recuperación de mensajes de una cola que está configurado para un diario es solamente aproximadamente un 20% más de recuperación mensajes sin registro en el diario, el real costo es problemas inesperados causados cuando un sin marcar, se ejecuta el servicio de MSMQ sin memoria o la máquina está fuera de espacio en disco

Esto funciona para mí. Bloquea la rosca a la espera de un mensaje. Cada ciclo de bucle comprueba el _bServiceRunning miembro de la clase para ver si el hilo debe abortar.

    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()

En mi humilde opinión que sólo se debe encender en diario en la cola. A continuación, se le garantiza una copia se mantiene de todos los mensajes que se han cometido a la cola, y que simplemente no es el caso con su intento laborous para hacer su propio mecanismo para registrar todo.

Mucho, mucho más fácil y más fiable es para registrar y eliminar los mensajes registrados en diario de forma programada, si quieres algo más fácil de leer que la propia cola (y ciertamente querría eso). Entonces realmente no importa qué tan rápido o no el proceso está funcionando, sólo es necesario para obtener los mensajes de una vez, y es en conjunto es sólo una manera mucho mejor para resolver el problema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top