C# MSMQ使用事务接收-回滚不使消息再次可用
我在一个叫做“MessageQueueReceive”的类中有这个 然后,我的处理循环有以下内容:-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)
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;
}