/// <summary>
        /// Shuts the processing pipeline down (base class specific part).
        /// This method must not throw exceptions.
        /// </summary>
        internal override void OnShutdownBase()
        {
            // tell the processing thread to terminate
            // (it will try to process the last messages and exit)
            mTerminateProcessingTask = true;
            mAsyncProcessingCancellationTokenSource?.CancelAfter(mShutdownTimeout);
            mTriggerAsyncProcessingEvent?.Set();
            mAsyncProcessingTask?.Wait();

            // the processing task should have completed its work
            Debug.Assert(mAsyncProcessingTask == null || mAsyncProcessingTask.IsCompleted);

            // the stack should be empty now...
            Debug.Assert(mAsyncProcessingMessageStack == null || mAsyncProcessingMessageStack.UsedItemCount == 0);

            // clean up processing thread related stuff
            mAsyncContextThread?.Join();
            mAsyncProcessingCancellationTokenSource?.Dispose();
            mAsyncContextThread  = null;
            mAsyncProcessingTask = null;
            mAsyncProcessingCancellationTokenSource = null;
            mAsyncProcessingMessageStack            = null;

            // perform pipeline stage specific cleanup
            try
            {
                OnShutdown();
            }
            catch (Exception ex)
            {
                // swallow exception to avoid crashing the application, if the exception is not handled properly
                Debug.Fail("The pipeline stage failed shutting down.", ex.ToString());
            }
        }
        /// <summary>
        /// Initializes the processing pipeline stage (base class specific part).
        /// </summary>
        internal override void OnInitializeBase()
        {
            try
            {
                // set up asynchronous processing
                mAsyncProcessingMessageStack            = new LocklessStack <LocalLogMessage>(mMessageQueueSize, false);
                mTriggerAsyncProcessingEvent            = new AsyncAutoResetEvent(false);
                mAsyncProcessingCancellationTokenSource = new CancellationTokenSource();
                mTerminateProcessingTask = false;
                mAsyncContextThread      = new AsyncContextThread();
                mAsyncProcessingTask     = mAsyncContextThread.Factory.Run(ProcessingTask);

                // Perform pipeline stage specific initialization
                OnInitialize();
            }
            catch (Exception)
            {
                Shutdown();
                throw;
            }
        }