void ProcessMessage(MessageTransportContext context) { var dispatched = false; try { _dispatcher(context.Unpacked); dispatched = true; } catch (ThreadAbortException) { // we are shutting down. Stop immediately return; } catch (Exception dispatchEx) { // if the code below fails, it will just cause everything to be reprocessed later, // which is OK (duplication manager will handle this) SystemObserver.Notify(new MessageDispatchFailed(context, context.QueueName, dispatchEx)); // quarantine is atomic with the processing _inbox.TryNotifyNack(context); } if (!dispatched) { return; } try { _inbox.AckMessage(context); // 3rd - notify. SystemObserver.Notify(new MessageAcked(context)); } catch (ThreadAbortException) { // nothing. We are going to sleep } catch (Exception ex) { // not a big deal. Message will be processed again. SystemObserver.Notify(new MessageAckFailed(ex, context)); } }