中转消息已处置



我在将中转消息标记为完成时遇到问题。

按预期工作的简单代码:

 private void OnMessageArrived(BrokeredMessage message)
 {
     var myObj= message.GetBody<MyObject>();
     //do things with myObj
     message.Complete();            
 }

当我尝试等待用户完成myObj时,出现异常:

中转消息已被处置

代码如下:

 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 中的分离对象,只是在这种情况下,对象从服务总线分离

编辑:

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

您不应该存储中转消息本身。当您调用 .Complete() 方法,根据文档,这是发生的事情:

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

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

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

在相关的代码中:

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

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

回调返回后,BrokeredMessage被释放。

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

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

当您要将其标记为完成时,会接收LockToken作为参数。

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

看看 ServiceBus LockToken。

您可以调用 Complete(lockToken)

最新更新