Сообщение не достигает MSMQ, когда сделано транзакционным - PullRequest
14 голосов
/ 28 марта 2012

У меня есть личный MSMQ, созданный на моей локальной машине. Я отправляю сообщения в очередь, используя следующий код C #. Когда я изменил очередь на транзакционную, сообщение не достигает MSMQ. Однако в методе Send не возникает исключение. Какое изменение мне нужно сделать, чтобы оно заработало?

using System;
using System.Messaging;
using System.Data;

public partial class _Default : System.Web.UI.Page
{
    //Sharing violation resulted from queue being open already for exclusive receive.
    MessageQueue helpRequestQueue = new MessageQueue(@".\Private$\MyPrivateQueue", false);
    protected void Page_Load(object sender, EventArgs e)
    {   
        bool isTransactionalQueue = false;    
        if (!System.Messaging.MessageQueue.Exists(@".\Private$\MyPrivateQueue"))    
        {    
            System.Messaging.MessageQueue.Create(@".\Private$\MyPrivateQueue", isTransactionalQueue);    
        }    
        SendMessage();    
        GetAllMessages();    
    }


    private void SendMessage()    
    {    
        System.Messaging.Message theMessage = new System.Messaging.Message("TimeNow is "+DateTime.Now.ToString());

        theMessage.Label = "Lijo " + DateTime.Now.ToString();

        theMessage.Priority = System.Messaging.MessagePriority.Normal;

        helpRequestQueue.Send(theMessage);    

    }


    private void GetAllMessages()   
    {    
        DataTable messageTable = new DataTable();    
        messageTable.Columns.Add("Label");    
        messageTable.Columns.Add("Body");        


        //Set Message Filters    
        MessagePropertyFilter filter = new MessagePropertyFilter();    
        filter.ClearAll();    
        filter.Body = true;    
        filter.Label = true;    
        filter.Priority = true;
        helpRequestQueue.MessageReadPropertyFilter = filter;

        //Get All Messages    
        System.Messaging.Message[] messages = helpRequestQueue.GetAllMessages();    
        System.Messaging.XmlMessageFormatter stringFormatter = new System.Messaging.XmlMessageFormatter(new string[] { "System.String" });


        for (int index = 0; index < messages.Length; index++)    
        {    
            string test = System.Convert.ToString(messages[index].Priority);
            messages[index].Formatter = stringFormatter;    
            messageTable.Rows.Add(new string[] {messages[index].Label,messages[index].Body.ToString() });

        }


        Gridview1.DataSource = messageTable;    
        Gridview1.DataBind();    
    }    

    private void ReceiveAndProcess()    
    {



    }           
}

Ответы [ 4 ]

21 голосов
/ 25 апреля 2012

Для очередей, которые вы создали как транснациональные, вы должны использовать версию Send (), которая включает параметр MessageQueueTransactionType.Самым большим разочарованием является то, что он не выдает никаких исключений или ошибок, как вы видели, но сообщение просто не появляется.

Итак, в вашем коде измените:

helpRequestQueue.Send(theMessage); 

до

helpRequestQueue.Send(theMessage, MessageQueueTransactionType.Single); 

Редактировать: Мой ответ - это еще один способ сделать это, кроме ответа Дэвида.

14 голосов
/ 08 февраля 2013

Транзакции не работают на non-transactional queues.Если вы используете эту форму:

using(MessageQueueTransaction tx = new MessageQueueTransaction())
{
    tx.Begin();
    queue.Send(message, tx);
    tx.Commit();
}

В нетранзакционной очереди сообщение будет потеряно и исключение не будет выдано.Вы можете проверить, является ли очередь транзакционной, в свойствах очереди в консоли управления очередью сообщений.

Лучше использовать

queue.Send(message, MessageQueueTransactionType.Automatic)
7 голосов
/ 28 марта 2012

Per MSDN , вот пример использования транзакционной очереди MSMQ:

    // Connect to a transactional queue on the local computer.
    MessageQueue queue = new MessageQueue(".\\exampleTransQueue");

    // Create a new message.
    Message msg = new Message("Example Message Body");

    // Create a message queuing transaction.
    MessageQueueTransaction transaction = new MessageQueueTransaction();

    try
    {
        // Begin a transaction.
        transaction.Begin();

        // Send the message to the queue.
        queue.Send(msg, "Example Message Label", transaction);

        // Commit the transaction.
        transaction.Commit();
    }
    catch(System.Exception e)
    {
        // Cancel the transaction.
        transaction.Abort();

        // Propagate the exception.
        throw e;
    }
    finally
    {
        // Dispose of the transaction object.
        transaction.Dispose();
    }

Вы должны рассматривать это как транзакцию БД - начните транзакцию, создав новый MSMQтранзакции, а затем либо зафиксировать, либо прервать операцию.

2 голосов
/ 29 марта 2012

Очередь и тип сообщения должны быть одинаковыми - в этом случае транзакционными. Если вы не получите исключение, используйте в своем коде журнал с отрицательным исходным кодом, чтобы помочь найти потерянные сообщения.

...