public IBrokeredMessage EndReceive(IAsyncResult result) { var msg = client.EndReceive(result); if (msg != null) { return(new BrokeredMessageWrapper(msg)); } return(null); }
private void ProcessBrokeredMessage <T>(Action <T> receiveHandler, SubscriptionClient subscriptionClient, IAsyncResult cb) { try { var brokeredMessage = subscriptionClient.EndReceive(cb); if (brokeredMessage != null) { var messageData = brokeredMessage.GetBody <T>(); try { receiveHandler(messageData); if (_receiveMode == ReceiveMode.PeekLock) { brokeredMessage.BeginComplete((result) => { var m = result.AsyncState as BrokeredMessage; if (m != null) { m.EndComplete(result); } }, brokeredMessage); } } catch (Exception) { // TODO: what happens if this loops? if (_receiveMode == ReceiveMode.PeekLock) { brokeredMessage.BeginAbandon((result) => { var m = result.AsyncState as BrokeredMessage; if (m != null) { m.EndAbandon(result); } }, brokeredMessage); } } } } catch (Exception ex) { Debug.WriteLine("BeginReceive threw exception"); if (OnError != null) { OnError(ex); // report the error if the user wants to know the error } } finally { Begin <T>(receiveHandler, subscriptionClient); } }
private void Begin <T>(Action <T> receiveHandler, SubscriptionClient subscriptionClient) { subscriptionClient.BeginReceive( TimeSpan.FromMinutes(5), (cb) => { var brokeredMessage = subscriptionClient.EndReceive(cb); if (brokeredMessage != null) { var messageData = brokeredMessage.GetBody <T>(); receiveHandler(messageData); Begin <T>(receiveHandler, subscriptionClient); } }, null); }
public void StopReceiving() { if (_subscriptionClient == null) // we already have a subscription { throw new InvalidOperationException("Subscription Client was not set. You must call StartReceiving first."); } if (_asyncResult != null) { _subscriptionClient.EndReceive(_asyncResult); } //if (_namespaceManager != null && _subscriptionClient != null) //{ // this.DeleteSubscription(); //} }
private static void RunLoop() { MessagingFactory factory = MessagingFactory.Create(); SubscriptionClient auditSubscriptionClient = factory.CreateSubscriptionClient("IssueTrackingTopic", "AuditSubscription", ReceiveMode.ReceiveAndDelete); var retryPolicy = new RetryPolicy <ServiceBusTransientErrorDetectionStrategy>(RetryStrategy.DefaultClientRetryCount); var waitTimeout = TimeSpan.FromSeconds(10); // Declare an action acting as a callback whenever a message arrives on a queue. AsyncCallback completeReceive = null; // Declare an action acting as a callback whenever a non-transient exception occurs while receiving or processing messages. Action <Exception> recoverReceive = null; // Declare a cancellation token that is used to signal an exit from the receive loop. var cts = new CancellationTokenSource(); // Declare an action implementing the main processing logic for received messages. Action <BrokeredMessage> processMessage = ((msg) => { // Put your custom processing logic here. DO NOT swallow any exceptions. Console.WriteLine(msg.Properties["HorseId"]); }); // Declare an action responsible for the core operations in the message receive loop. Action receiveMessage = (() => { // Use a retry policy to execute the Receive action in an asynchronous and reliable fashion. retryPolicy.ExecuteAction ( (cb) => { // Start receiving a new message asynchronously. auditSubscriptionClient.BeginReceive(waitTimeout, cb, null); }, (ar) => { // Make sure we are not told to stop receiving while we were waiting for a new message. if (!cts.IsCancellationRequested) { // Complete the asynchronous operation. This may throw an exception that will be handled internally by retry policy. BrokeredMessage msg = auditSubscriptionClient.EndReceive(ar); // Check if we actually received any messages. if (msg != null) { // Make sure we are not told to stop receiving while we were waiting for a new message. if (!cts.IsCancellationRequested) { try { // Process the received message. processMessage(msg); // With PeekLock mode, we should mark the processed message as completed. if (auditSubscriptionClient.Mode == ReceiveMode.PeekLock) { // Mark brokered message as completed at which point it's removed from the queue. msg.Complete(); } } catch { // With PeekLock mode, we should mark the failed message as abandoned. if (auditSubscriptionClient.Mode == ReceiveMode.PeekLock) { // Abandons a brokered message. This will cause Service Bus to unlock the message and make it available // to be received again, either by the same consumer or by another completing consumer. msg.Abandon(); } // Re-throw the exception so that we can report it in the fault handler. throw; } finally { // Ensure that any resources allocated by a BrokeredMessage instance are released. msg.Dispose(); } } else { // If we were told to stop processing, the current message needs to be unlocked and return back to the queue. if (auditSubscriptionClient.Mode == ReceiveMode.PeekLock) { msg.Abandon(); } } } } // Invoke a custom callback method to indicate that we have completed an iteration in the message receive loop. completeReceive(ar); }, () => { Console.WriteLine("Success Handler"); }, (ex) => { // Invoke a custom action to indicate that we have encountered an exception and // need further decision as to whether to continue receiving messages. recoverReceive(ex); }); }); // Initialize a custom action acting as a callback whenever a message arrives on a queue. completeReceive = ((ar) => { if (!cts.IsCancellationRequested) { // Continue receiving and processing new messages until we are told to stop. receiveMessage(); } }); // Initialize a custom action acting as a callback whenever a non-transient exception occurs while receiving or processing messages. recoverReceive = ((ex) => { // Just log an exception. Do not allow an unhandled exception to terminate the message receive loop abnormally. Console.WriteLine(ex.Message); if (!cts.IsCancellationRequested) { // Continue receiving and processing new messages until we are told to stop regardless of any exceptions. receiveMessage(); } }); // Start receiving messages asynchronously. receiveMessage(); // Perform any other work. Message will keep arriving asynchronously while we are busy doing something else. // Stop the message receive loop gracefully. cts.Cancel(); }
/// <summary> /// Receives the messages in an endless asynchronous loop. /// </summary> private void ReceiveMessages(CancellationToken cancellationToken) { // Declare an action to receive the next message in the queue or end if cancelled. Action receiveNext = null; // Declare an action acting as a callback whenever a non-transient exception occurs while receiving or processing messages. Action <Exception> recoverReceive = null; // Declare an action responsible for the core operations in the message receive loop. Action receiveMessage = () => { // Use a retry policy to execute the Receive action in an asynchronous and reliable fashion. receiveRetryPolicy.ExecuteAction ( cb => { // Start receiving a new message asynchronously. client.BeginReceive(ReceiveLongPollingTimeout, cb, null); }, ar => { // Complete the asynchronous operation. This may throw an exception that will be handled internally by retry policy. try { return(client.EndReceive(ar)); } catch (TimeoutException) { // TimeoutException is not just transient but completely expected in this case, so not relying on Topaz to retry return(null); } }, msg => { // Process the message once it was successfully received if (processInParallel) { // Continue receiving and processing new messages asynchronously Task.Factory.StartNew(receiveNext); } // Check if we actually received any messages. if (msg != null) { var roundtripStopwatch = Stopwatch.StartNew(); long schedulingElapsedMilliseconds = 0; long processingElapsedMilliseconds = 0; Task.Factory.StartNew(() => { var releaseAction = MessageReleaseAction.AbandonMessage; try { instrumentation.MessageReceived(); schedulingElapsedMilliseconds = roundtripStopwatch.ElapsedMilliseconds; // Make sure the process was told to stop receiving while it was waiting for a new message. if (!cancellationToken.IsCancellationRequested) { try { try { // Process the received message. releaseAction = InvokeMessageHandler(msg); processingElapsedMilliseconds = roundtripStopwatch.ElapsedMilliseconds - schedulingElapsedMilliseconds; instrumentation.MessageProcessed(releaseAction.Kind == MessageReleaseActionKind.Complete, processingElapsedMilliseconds); } catch { processingElapsedMilliseconds = roundtripStopwatch.ElapsedMilliseconds - schedulingElapsedMilliseconds; instrumentation.MessageProcessed(false, processingElapsedMilliseconds); throw; } } finally { if (roundtripStopwatch.Elapsed > TimeSpan.FromSeconds(45)) { dynamicThrottling.Penalize(); } } } } finally { // Ensure that any resources allocated by a BrokeredMessage instance are released. ReleaseMessage(msg, releaseAction, processingElapsedMilliseconds, schedulingElapsedMilliseconds, roundtripStopwatch); } if (!processInParallel) { // Continue receiving and processing new messages until told to stop. receiveNext.Invoke(); } }); } else { dynamicThrottling.NotifyWorkCompleted(); if (!processInParallel) { // Continue receiving and processing new messages until told to stop. receiveNext.Invoke(); } } }, ex => { // Invoke a custom action to indicate that we have encountered an exception and // need further decision as to whether to continue receiving messages. recoverReceive.Invoke(ex); }); }; // Initialize an action to receive the next message in the queue or end if cancelled. receiveNext = () => { dynamicThrottling.WaitUntilAllowedParallelism(cancellationToken); if (!cancellationToken.IsCancellationRequested) { dynamicThrottling.NotifyWorkStarted(); // Continue receiving and processing new messages until told to stop. receiveMessage.Invoke(); } }; // Initialize a custom action acting as a callback whenever a non-transient exception occurs while receiving or processing messages. recoverReceive = ex => { // Just log an exception. Do not allow an unhandled exception to terminate the message receive loop abnormally. Trace.TraceError("An unrecoverable error occurred while trying to receive a new message from subscription {1}:\r\n{0}", ex, subscription); dynamicThrottling.NotifyWorkCompletedWithError(); if (!cancellationToken.IsCancellationRequested) { // Continue receiving and processing new messages until told to stop regardless of any exceptions. TaskEx.Delay(10000).ContinueWith(t => receiveMessage.Invoke()); } }; // Start receiving messages asynchronously. receiveNext.Invoke(); }