在反序列化异常的情况下从 MSMQ 中删除消息

Removing message from MSMQ in case of deserialization exception

目前我正在开发 widows 服务,该服务正在接收来自本地私有 MSMQ 的消息。队列是事务性的。

接收是这样完成的:

public void ReceiveAndSaveData(MessageQueue queue, MsmqDbContext context)
        {
            var message = new Message();
            try
            {
                using (var tx = new MessageQueueTransaction())
                {
                    tx.Begin();
                    message = queue.Receive(tx);
                    var bodyReader = new StreamReader(message.BodyStream);
                    var jsonBody = bodyReader.ReadToEnd();
                    var messageData = JsonConvert.DeserializeObject<QueueMessage>(jsonBody);

                    /*THERE IS SOME DATA PROCESSING*/


                    tx.Commit();
                }
            }
            catch (JsonSerializationException e)
            {
                Logger.WriteError(new LogDetail("Error occured during deserializing incoming data.", e, message.Id));

            }
            catch (Exception e)
            {
                Logger.WriteError(new LogDetail("Error occured during saving data to database", e, message.Id));
            }
        }

如果出现 JsonSerializationException,我想从当前队列中删除这条消息。有人知道如何解决这个问题吗?

也将 tx.Commit() 放入 JsonSerializationException

catch 块中

使用 Abort() 方法并将 tx-object 创建移到 try-catch 块之外。

public void ReceiveAndSaveData(MessageQueue queue, MsmqDbContext context)
{
    bool exceptionOccurred = false;
    var message = new Message();
    MessageQueueTransaction tx;
    try
    {
        exceptionOccurred = false;
        using (tx = new MessageQueueTransaction())
        {
            tx.Begin();
            message = queue.Receive(tx);
            var bodyReader = new StreamReader(message.BodyStream);
            var jsonBody = bodyReader.ReadToEnd();
            var messageData = JsonConvert.DeserializeObject<QueueMessage>(jsonBody);

            /*THERE IS SOME DATA PROCESSING*/

        }
    }
    catch (JsonSerializationException e)
    {
        Logger.WriteError(new LogDetail("Error occured during deserializing incoming data.", e, message.Id));
        tx.Abort(); //Rolls back the pending internal transaction
        exceptionOccurred = true;
    }
    catch (Exception e)
    {
        Logger.WriteError(new LogDetail("Error occured during saving data to database", e, message.Id));
         exceptionOccurred = true;
    }
    finally
    {
        if(!exceptionOccurred)
            tx.Commit();
    }
}

Abort() MSDN