2016-03-07 3 views
5

У меня есть проблема с маркировкой BrokeredMessage как завершено.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

EDIT:

Важно, чтобы сообщение было полностью заполнено только после нажатия кнопки пользователя. В случае падения AC (или подобных вещей) я хочу, чтобы сообщения остались на Service Bus Topic, чтобы в следующий раз при запуске приложения пользователя он снова получил сообщения, которые он не обработал.

ответ

2

Вы не должны хранить брокерское сообщение. При вызове метода .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); 
+0

Не могли бы вы порекомендовать решение этой проблемы: 1. Полученное сообщение, его данные разбиты на куски и отправлены на асинхронную обработку. Мы хотим заблокировать сообщение до тех пор, пока его данные не будут обработаны пользователем, который его приобрел. 2. Если возникает исключение или пользователь выходит из программы, разблокируйте сообщение, чтобы другой пользователь мог его обработать позже. 3. Если/когда последняя часть данных обрабатывается, удалите сообщение из ServiceBus с момента его данные были надлежащим образом обработаны. – ErroneousFatality

+0

Да. Вы не будете вызывать Complete() в сообщении, пока не закончите. –

+0

Извините, если я ошибаюсь, но это именно то, что делает OP. Он сохраняет сообщение в словаре, поэтому он может вызвать «Полный» после завершения обработки асинхронизации. Вы рекомендовали вместо этого не делать этого и сохранять только данные, которые он обрабатывает. Как он тогда вызовет Complete в сообщении после асинхронного процесса? – ErroneousFatality

0

Посмотрите на ServiceBus LockToken.

Вы можете позвонить Complete (lockToken)

+0

Все те же исключения _brokeredmessage был удален_ – topolm

2

Это очень неявное и не указано также в документации, насколько я знаю, но когда вы подписались на SB Тема/Подписку Вы можете получить доступ только BrokeredMessage объекта в пределах области выполнения делегата callback OnMessage, который вы передаете по адресу SubscriptionClient.OnMessage.

Как только обратный вызов возвращается, удаляется BrokeredMessage.

Если вы хотите кэшировать сообщение и пометить его как полный/заброшенный/deadletter, вы должны кэшировать BrokeredMessage.LockToken, а также любое другое имущество, вам нужно как тело сообщения, и использовать

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

, которые получают LockToken в качестве параметра, если вы хотите пометить их как завершенные.

Смежные вопросы