C# MSMQ使用事务接收-回滚不使消息再次可用

C# MSMQ使用事务接收-回滚不使消息再次可用,c#,.net,transactions,msmq,message-queue,C#,.net,Transactions,Msmq,Message Queue,我在一个叫做“MessageQueueReceive”的类中有这个 然后,我的处理循环有以下内容:- while (!Abort) { try { tran = this.Queue.BlockingReceive(out msg); if (msg != null) { // Process message here if (tran != null)

我在一个叫做“MessageQueueReceive”的类中有这个

然后,我的处理循环有以下内容:-

while (!Abort)
{
    try
    {
        tran = this.Queue.BlockingReceive(out msg);

        if (msg != null)
        {
            // Process message here

            if (tran != null)
                tran.Commit();
        }
    }
    catch (Exception ex)
    {
        if (tran != null)
            tran.Abort();

    }
}
控制面板工具显示我使用的消息队列是事务性的。日志队列未启用

此代码创建队列:-

private static MessageQueue CreateMessageQueue(string queueName, bool transactional = false)
{
    MessageQueue messageQueue = MessageQueue.Create(queueName, transactional);
    messageQueue.SetPermissions("Administrators", MessageQueueAccessRights.FullControl,
            AccessControlEntryType.Allow);
    return messageQueue;
}
调用时,事务参数设置为“true”

我发现,当消息处理过程中发生异常时,会调用trans.Abort,但此时我希望消息返回到队列。然而,这并没有发生,消息也丢失了


我错过了什么明显的东西吗?有人知道我做错了什么吗?

需要将您的队列创建为事务性队列,以获得您想要的

编辑:


好吧,如果您的队列是事务性的,那么这就表明您在错误处理您的事务,尽管我看不出它是如何具体发生的。我将更改您的阻止接收方法以返回消息。我会将MessageQueueTransaction的创建移动到外部方法。如果在同一个方法中有Begin、Commit和Abort方法调用,那么代码将更易于维护。

感谢所有的评论。我确实按照RussellMcClure的建议重新组织了代码,我试图创建简单的测试用例,但无法重现问题

最后,问题根本不是我在找什么(这种情况发生的频率有多高?)

在我的管道中,我有一个重复的消息检查器。我的系统处理的“消息”来自WAN上的远程设备,偶尔也会复制线路上的消息

当从MSMQ中提取消息时,它将通过复制检查器和数据库编写器传递。如果数据库写入程序失败,则选中的重复项不会从其表中删除哈希。当进程再次尝试循环时,它将再次从队列中获得相同的消息,因为当数据库写入程序失败时,MSMQ事务已回滚。然而,在第二次尝试时,重复检查器会发现它以前看到过该消息,并默默地将其吞下


修复方法是让复制检查器发现来自链中下一个链接的异常,并回滚它所做的任何操作。

Hi!这些队列肯定是作为事务性队列创建的。如果我查看计算机管理->服务和应用程序->消息队列中的队列属性,它显示为事务性。您正在侦听器服务上接收的队列是本地队列吗?是的,发送和接收进程以及队列都在同一个框中。它们是私人队列。我还在几个不同的框中运行相同的代码,并且在所有的框中看到相同的问题。这表明它与这段代码有关,而不是机器上的一些奇怪的东西。我想这是个明显的问题。您确定它在中遇到异常并中止吗?是否有可能在捕获的消息处理代码中抛出异常,然后将其扔掉,这样它就不会在异常处理程序中冒泡,并在异常处理程序中中止?
private static MessageQueue CreateMessageQueue(string queueName, bool transactional = false)
{
    MessageQueue messageQueue = MessageQueue.Create(queueName, transactional);
    messageQueue.SetPermissions("Administrators", MessageQueueAccessRights.FullControl,
            AccessControlEntryType.Allow);
    return messageQueue;
}