/// <summary> /// This method causes the communication listener to close. Close is a terminal state and /// this method allows the communication listener to transition to this state in a /// graceful manner. /// </summary> /// <param name="cancellationToken">Cancellation token</param> /// <returns> /// A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents outstanding operation. /// </returns> public async Task CloseAsync(CancellationToken cancellationToken) { WriteLog("Service Bus Communication Listener closing"); IsClosing = true; _stopProcessingMessageTokenSource.Cancel(); //Wait for Message processing to complete.. await Task.WhenAny( // Timeout task. Task.Delay(CloseTimeout, cancellationToken), // Wait for all processing messages to finish by stealing semaphore entries. Task.Run(() => { for (int i = 0; i < (MaxConcurrentCalls ?? 1); i++) { // ReSharper disable once AccessToDisposedClosure // ReSharper disable once EmptyGeneralCatchClause try { ProcessingMessage.Wait(cancellationToken); } catch { } } }, cancellationToken)); ProcessingMessage.Dispose(); await CloseImplAsync(cancellationToken); }
/// <summary> /// Will pass an incoming message to the <see cref="Receiver"/> for processing. /// </summary> /// <param name="message"></param> /// <param name="cancellationToken"></param> protected async Task ReceiveMessageAsync(Message message, CancellationToken cancellationToken) { try { ProcessingMessage.Wait(cancellationToken); var combined = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, StopProcessingMessageToken).Token; await Receiver.ReceiveMessageAsync(message, combined); } finally { ProcessingMessage.Release(); } }
/// <summary> /// Will pass an incoming message to the <see cref="Receiver"/> for processing. /// </summary> /// <param name="message"></param> /// <param name="cancellationToken"></param> protected async Task ReceiveMessageAsync(Message message, CancellationToken cancellationToken) { try { if (IsClosing) { // We want the thread to sleep and not return immediately. // Returning immediately could increment the message fail count and send it to dead letter. Thread.Sleep(CloseTimeout); return; } ProcessingMessage.Wait(cancellationToken); var combined = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, StopProcessingMessageToken).Token; await Receiver.ReceiveMessageAsync(message, combined); } finally { ProcessingMessage.Release(); } }