【问题标题】:BrokeredMessage disposedBrokeredMessage 已处理
【发布时间】:2016-03-07 15:25:37
【问题描述】:

我无法将我的 BrokeredMessage 标记为完成。

按预期工作的简单代码:

 private void OnMessageArrived(BrokeredMessage message)
 {
     var myObj= message.GetBody<MyObject>();

     //do things with myObj

     message.Complete();            
 }

当我尝试等待用户完成 myObj 我得到异常:

brokeredmessage 已处理

代码如下:

 private Dictionary<long, BrokeredMessage> ReceivedMessages;      
 ReceivedMessages = new Dictionary<long, BrokeredMessage>();

 private void OnMessageArrived(BrokeredMessage message)
 {
     var myObj= message.GetBody<MyObject>();
     ReceivedMessages.Add(myObj.Id, message);

     //do things with myObj      
 }

 private void Button_Click(object sender, RoutedEventArgs e)
 {
     // get myObj on which user clicked

     ReceivedMessages[myObj.Id].Complete();
     ReceivedMessages.Remove(myObj.Id);        
 }

在我看来,ServiceBus 以某种方式失去了与 c#

中实际对象的连接

类似于 EF 中的分离对象,只是在这种情况下,对象与 ServiceBus

分离

编辑:

只有在用户单击按钮后才将消息标记为完成对我来说很重要。 如果 AC 出现故障(或类似情况),我希望消息仍保留在 Service Bus 主题 上,以便下次用户启动应用程序时,他将再次收到他未处理的消息。

【问题讨论】:

    标签: c# servicebus brokeredmessage


    【解决方案1】:

    您不应存储代理消息本身。当您调用 .Complete() 方法时,会发生这种情况according to the documentation

    完成一条消息的接收操作,并指示该消息应标记为已处理并删除

    您应该做的是在您的字典中存储 MyObject 类型的对象,因为代理消息将在完成后被销毁。

    private Dictionary<long, MyObject> ReceivedMessages;      
    ReceivedMessages = new Dictionary<long, MyObject>();
    

    在相关的代码中:

     var myObj= message.GetBody<MyObject>();
     ReceivedMessages.Add(myObj.Id, myObj);
    

    【讨论】:

    • 您能否推荐一个解决此问题案例的方法: 1. 收到消息,将其数据分成几部分并发送到异步处理。我们希望锁定消息,直到它的数据被获取它的用户处理。 2. 如果发生异常或用户退出程序,解锁消息以便其他用户稍后可以处理它 3. 如果/当处理最后一条数据时,则从 ServiceBus 中删除消息,因为其数据已正确处理.
    • 是的。在完成之前,您推迟对消息调用 Complete()。
    • 如果我错了,请原谅,但这正是 OP 正在做的事情。他将消息保存在字典中,以便在异步处理结束后调用 Complete。您建议他不要这样做,而只保存他正在处理的数据。在异步过程之后,他将如何在消息上调用 Complete?
    • 非常感谢您的耐心等待。因此,除非您愿意,否则我觉得有义务向您正确解释我们的(我的和 OPs)系统,而不期待您的进一步帮助。 ServiceBus 队列充满了票证,一个分布式的版主网络需要检查、修改(如果需要),最后通过 GUI 批准或拒绝它。这就是为什么我们希望在获取内容后将消息保留在 Bus 中,直到版主完成它们。
    • 我相信您想要的是代理消息会话。这里本质上是为队列/订阅启用会话,而不是处理调用 AcceptMessageSession 的消息。消息的 SessionID 属性将确定它属于哪个会话。每个会话都有一个可用的状态,您可以通过 MessageSession 上的 GetState 和 SetState 访问它。更多信息在这里:code.msdn.microsoft.com/Brokered-Messaging-Session-41c43fb4
    【解决方案2】:

    据我所知,这是非常隐含的,并且在文档中没有很好地说明,但是当您订阅 SB 主题/订阅时,您只能在 OnMessage 回调的执行范围内访问 BrokeredMessage 对象委托你提供给SubscriptionClient.OnMessage

    一旦回调返回,BrokeredMessage 就会被释放。

    如果您想缓存消息并将其标记为完整/已放弃/死信,您应该缓存BrokeredMessage.LockToken,以及您需要的任何其他属性(如消息正文),并使用

    • SubscriptionClient.Complete
    • SubscriptionClient.Abandon
    • SubscriptionClient.Deadletter

    当您想将它们标记为完成时,它会接收 LockToken 作为参数。

    【讨论】:

      【解决方案3】:

      如果您正在执行异步方法,我发现这也是同样的问题,消息被分派并且在等待发生时,消息已经被释放。我只希望我早点找到这篇文章..

      【讨论】:

        【解决方案4】:

        看看 ServiceBus LockToken。

        你可以调用 Complete(lockToken)

        【讨论】:

        • 还是同样的异常brokeredmessage已经被处理
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-25
        • 1970-01-01
        • 2021-02-07
        • 2020-02-26
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多