private void AcceptSession(CancellationToken cancellationToken) { dynamicThrottling.WaitUntilAllowedParallelism(cancellationToken); if (!cancellationToken.IsCancellationRequested) { // Initialize a custom action acting as a callback whenever a non-transient exception occurs while accepting a session. Action <Exception> recoverAcceptSession = 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 accept a session in subscription {1}:\r\n{0}", ex, subscription); dynamicThrottling.Penalize(); if (!cancellationToken.IsCancellationRequested) { // Continue accepting new sessions until told to stop regardless of any exceptions. TaskEx.Delay(10000).ContinueWith(t => AcceptSession(cancellationToken)); } }; receiveRetryPolicy.ExecuteAction( cb => client.BeginAcceptMessageSession(AcceptSessionLongPollingTimeout, cb, null), ar => { // Complete the asynchronous operation. This may throw an exception that will be handled internally by retry policy. try { return(client.EndAcceptMessageSession(ar)); } catch (TimeoutException) { // TimeoutException is not just transient but completely expected in this case, so not relying on Topaz to retry return(null); } }, session => { if (session != null) { instrumentation.SessionStarted(); dynamicThrottling.NotifyWorkStarted(); // starts a new task to process new sessions in parallel when enough threads are available Task.Factory.StartNew(() => AcceptSession(cancellationToken), cancellationToken); ReceiveMessagesAndCloseSession(session, cancellationToken); } else { AcceptSession(cancellationToken); } }, recoverAcceptSession); } }