如何正常关闭Azure ServiceBus QueueClient?

时间:2015-04-05 11:13:31

标签: c# azure azureservicebus

当我致电QueueClient.Close()时,它总是会引发异常:

  

由于实体已关闭,因此无法执行操作   或中止。

即使队列为空,也会引发异常。

虽然我使用OnMessageOptions.ExceptionReceived处理它,但它让我烦恼。我的代码有问题吗?

如何优雅地停止QueueClient?

[开始,然后停止发送消息]

// create a QueueClient with Exception handler.
var queueClient = queueManager.GetStorage<UpdateTriggerQueueClient>();
var options = new OnMessageOptions
{
    AutoComplete = false
};
// When the Close() called, it always handles an exception.
options.ExceptionReceived += (sender, args) => 
    logger.Error("An excepion occurred.", args.Exception);

// prepare a CancellationTokenSource.
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;

// start message pump.
queueClient.OnMessageAsync(async message => 
            await DoWork(message, cancellationToken), options);

// sometime after, stop(cancel) the work.
Task.Delay(5000).Wait();
cancellationTokenSource.Cancel();

// some code to wait every in-progress messages finished.
// ...

// close the client.
queueClient.Close();

[DoWork方法]

private async Task DoWork(BrokeredMessage message, CancellationToken cancellationToken)
{
    logger.Trace("begin work");
    // Do something cancellable work.
    await Task.Delay(500, cancellationToken)
        .ContinueWith(async t =>
        {
            // complete the message when the task completed,
            // otherwise, abandon the message.
            if (t.Status == TaskStatus.RanToCompletion)
            {
                await message.CompleteAsync();
            }
            else
            {
                await message.AbandonAsync();
            }
        })
        .ContinueWith(t =>
        {
            // cleanup
            logger.Trace("end work");
        });
}

3 个答案:

答案 0 :(得分:0)

您可以通过以下方式更新订阅来停止接收所有邮件:

_namespaceManager.UpdateSubscription(new SubscriptionDescription(_strTopic, _strSubscription) 
  { 
     Status = EntityStatus.ReceiveDisabled
  });

这可能会解决您的问题,即使它并不是您所要求的。 (我也试图找出如何正确关闭()。

您还需要更新状态以便再次开始接收。

答案 1 :(得分:0)

我认为了解IQueueClient接口的工作方式非常重要。收到消息后,您会收到称为CancellationToken的消息。 CancellationToken使您可以配合线程,线程池工作项或Task对象之间的取消。在这种情况下,您需要处理Azure Service Bus连接。这就是我要做的,控制连接是否已关闭,如果是这种情况,我将检查我们收到的消息是否仍然有效。

public async Task<object> ReceiveAsync(Message message, CancellationToken token)
{
            //If the connection still open, we do something
            if (!token.IsCancellationRequested)
            {
             ...
            }
}

答案 2 :(得分:-1)

我在https://msdn.microsoft.com/en-us/library/azure/hh528527.aspx上读到,不应该调用close,因为连接是由消息工厂管理的。

this.mSubscriptionClient.OnMessage(
             (pMessage) =>
             {
                 try
                 {
                     // Will block the current thread if Stop is called.
                     this.mPauseProcessingEvent.WaitOne();

                     // Execute processing task here
                     pProcessMessageTask(pMessage);
                 }
                 catch(Exception ex)
                 {
                     this.RaiseOnLogMessageEvent(pMessage, ex);
                 }
             },
             options);

然后当你准备停止时

this.mPauseProcessingEvent.Reset();
mSubscriptionClient.Close();

数据类型为

private ManualResetEvent mPauseProcessingEvent;