Gracefully handle RenewMessageLockTask (#548)

In the MessageReceivePump class the RenewMessageLockTask is now canceled
gracefully instead of raise a TaskCancelledException and the catch it
again.

The code now doesn't await the canceled task, but await a new task which
just returns the canceled task. And check if the delay task is canceled
to determine if the RenewMessageLockTask should be completed or not.

Fixes #547.
This commit is contained in:
Håvar Nøvik 2018-09-25 02:28:35 +02:00 коммит произвёл Neeraj Makam
Родитель c91efcbead
Коммит b7b1106cfb
1 изменённых файлов: 12 добавлений и 4 удалений

Просмотреть файл

@ -231,7 +231,16 @@ namespace Microsoft.Azure.ServiceBus
{ {
var amount = MessagingUtilities.CalculateRenewAfterDuration(message.SystemProperties.LockedUntilUtc); var amount = MessagingUtilities.CalculateRenewAfterDuration(message.SystemProperties.LockedUntilUtc);
MessagingEventSource.Log.MessageReceiverPumpRenewMessageStart(this.messageReceiver.ClientId, message, amount); MessagingEventSource.Log.MessageReceiverPumpRenewMessageStart(this.messageReceiver.ClientId, message, amount);
await Task.Delay(amount, renewLockCancellationToken).ConfigureAwait(false);
// We're awaiting the task created by 'ContinueWith' to avoid awaiting the Delay task which may be canceled
// by the renewLockCancellationToken. This way we prevent a TaskCanceledException.
var delayTask = await Task.Delay(amount, renewLockCancellationToken)
.ContinueWith(t => t, TaskContinuationOptions.ExecuteSynchronously)
.ConfigureAwait(false);
if (delayTask.IsCanceled)
{
break;
}
if (!this.pumpCancellationToken.IsCancellationRequested && if (!this.pumpCancellationToken.IsCancellationRequested &&
!renewLockCancellationToken.IsCancellationRequested) !renewLockCancellationToken.IsCancellationRequested)
@ -248,10 +257,9 @@ namespace Microsoft.Azure.ServiceBus
{ {
MessagingEventSource.Log.MessageReceiverPumpRenewMessageException(this.messageReceiver.ClientId, message, exception); MessagingEventSource.Log.MessageReceiverPumpRenewMessageException(this.messageReceiver.ClientId, message, exception);
// TaskCanceled is expected here as renewTasks will be cancelled after the Complete call is made.
// ObjectDisposedException should only happen here because the CancellationToken was disposed at which point // ObjectDisposedException should only happen here because the CancellationToken was disposed at which point
// this renew exception is not relevant anymore. Lets not bother user with this exception. // this renew exception is not relevant anymore. Lets not bother user with this exception.
if (!(exception is TaskCanceledException) && !(exception is ObjectDisposedException)) if (!(exception is ObjectDisposedException))
{ {
await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.RenewLock).ConfigureAwait(false); await this.RaiseExceptionReceived(exception, ExceptionReceivedEventArgsAction.RenewLock).ConfigureAwait(false);
} }