Как правильно отказаться от подписки на обработчики событий из MSMQ

#.net #msmq

#.net #msmq

Вопрос:

Есть ли здесь способ подать сигнал MSMQ о разблокировке подписчиков, которые заблокированы при получении BeginReceive?

В основном я использую асинхронный MSMQ API для чтения сообщений, подобных этому:

 public void Start()
{
    this.queue.ReceiveCompleted  = this.ReceiveCompleted;
    this.queue.BeginReceive();
}

void ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
    this.queue.EndReceive(e.AsyncResult);

    try
    {
        var m = e.Message;
        m.Formatter = this.formatter;

        this.Handle(m.Body);
    }
    finally
    {
        this.queue.BeginReceive();
    }
}

public void Stop()
{
    this.queue.ReceiveCompleted -= this.ReceiveCompleted;
    //Force an EndReceive here maybe or somehow indicate that 
    //the BeginReceive set above should "unblock"
    this.queue.Dispose();
}
  

Вопросы:

1) Я хотел бы подать сигнал MSMQ в методе Stop(), чтобы разблокировать текущий BeginReceive(). ПРИМЕЧАНИЕ: я знаю о перегрузке BeginReceive, которая принимает тайм-аут. Я бы предпочел избегать тайм-аута и периодического цикла, это кажется расточительным. Возможно ли это вообще? Если нет, гарантирует ли удаление очереди, что все зарегистрированные делегаты будут очищены должным образом?

2) Могут ли повторные вызовы BeginReceive в «ReceiveCompleted» вызывать какие-либо утечки? т. Е. Требуется ли какая-либо другая очистка, кроме отмены подписки делегата в Stop()?

 this.queue.ReceiveCompleted -= this.ReceiveCompleted;
  

Ответ №1:

1) Да, вы просто закрываете очередь. Когда вы это сделаете, вы должны увидеть вызов ReceiveCompleted с кодом ошибки 0xC0000120, который определен как STATUS_CANCELLED с текстом «Запрос ввода-вывода был отменен».

2) Вы должны вызвать BeginReceive в вашем событии ReceiveCompleted, чтобы продолжить получать сообщения.