internal void TerminateDispatcher(string dispatcherId)
        {
            Thread.Sleep(3000);

            var poisonPill = new PoisonPill
            {
                EffectOnCurrentWork = PoisonPillEffect.Kill,
                DispatcherId = DispatcherId.FromString(dispatcherId)
            };

            SendingBus.Send(poisonPill, poisonPill.DispatcherId.PoisonPillSubscriptionId, StorageType.NonPersistent);

            Thread.Sleep(10000);
        }
        private void TakePoisonPill(PoisonPill poisonPill)
        {
            try
            {
                if (IsDisposed)
                    return;

                Log.DispatcherActivity(Repository.Settings.DispatcherId, DispatcherActivity.PoisonPillWasReceived, poisonPill);

                if (poisonPill.DispatcherId != Repository.Settings.DispatcherId)
                    return;

                // Kill the process imediatelly non-gracefully
                if (poisonPill.EffectOnCurrentWork == PoisonPillEffect.Kill)
                {
                    Log.Error("Poison Pill with Kill request received! Terminating the process now...");
                    Environment.Exit(0);
                }

                // If another poison pill request is already being processed
                if (CancellationTokenForCheckIfDispatcherShouldBeKeptAliveThatMuchTimeAfterInitialized.IsCancellationRequested)
                    return;

                IsTakingPoisonPill = true;

                // Stop checking if can still be alive
                CancellationTokenForCheckIfDispatcherShouldBeKeptAliveThatMuchTimeAfterInitialized.Cancel();

                // Stop receiving pending work requests.
                CancellationTokenForCheckingPendingJobs.Cancel();

                // Wait the execution of the current work requests
                if (poisonPill.EffectOnCurrentWork == PoisonPillEffect.Wait)
                {
                    Thread.CurrentThread.SleepWhile(
                        () => ExecutingWorkers.Count > 0,
                        Repository.Settings.MaximumExecutionTime,
                        TimeoutWaitingWorkerToFinish);
                }

                // Abort the execution of the current work requests
                if (poisonPill.EffectOnCurrentWork == PoisonPillEffect.Abort)
                {
                    CancellationTokenForExecutionOfJob.Cancel();

                    Log.DispatcherActivity(Repository.Settings.DispatcherId, DispatcherActivity.AbortedAllWorkerThreads);
                }

                // Cancel the execution of the current work requests
                if (poisonPill.EffectOnCurrentWork == PoisonPillEffect.Cancel)
                {
                    CancellationTokenForExecutionOfJob.Cancel();

                    Thread.CurrentThread.SleepWhile(
                        () => ExecutingWorkers.Count > 0,
                        Repository.Settings.MaximumExecutionTime,
                        TimeoutWaitingWorkerToFinish);
                }

                Log.DispatcherActivity(Repository.Settings.DispatcherId, DispatcherActivity.PoisonPillWasTaken, poisonPill);

                // Must dispose in another thread to allow the handler that received the poison pill 
                // to acknoledge the message before the connection is disposed
                DisposeAsync();
            }
            catch (ThreadAbortException tae)
            {
                Log.Info(tae as Exception, "ThreadAbortException while taking poison pill!");
            }
            catch (Exception e)
            {
                Log.Error(e, "Exception taking poison pill!");
                Environment.Exit(0);
            }
        }
        internal static void DispatcherActivity(this Logger log, DispatcherId dispatcherId, DispatcherActivity activity, PoisonPill poisonPill = null, Exception exception = null, bool logAsError = true)
        {
            var logEntry = new DispatcherActivityLogEntry
            {
                DispatcherId = dispatcherId,
                Activity = activity,
                PoisonPill = poisonPill,
                Exception = exception
            };

            if (exception == null)
            {
                if (activity == Dispatching.DispatcherActivity.CheckingForUnfinishedJobs)
                    log.Debug(logEntry);
                else
                    log.Info(logEntry);
            }
            else if (logAsError)
                log.Error(exception, logEntry.ToString());
            else
                log.Info(exception, logEntry.ToString());
        }
        internal void TerminateApplication()
        {
            ReceivingBus.Receive<LifeSignal>(ComputationalUnit.Settings.DispatcherId.FromString(DispatcherId).LifeSignalSubscriptionId, message =>
            {
                lock (LatestLifeSignals)
                {
                    LatestLifeSignals[DispatcherId] = (LifeSignal)message;
                }
            });

            var settings = BootstrapSettings.DispatcherSettings.Single(s => s.DispatcherId.Value.StartsWith(DispatcherId));

            lock (LatestLifeSignals)
            {
                LifeSignal latestLifeSignal;
                if (LatestLifeSignals.TryGetValue(settings.DispatcherId.Value, out latestLifeSignal))
                {
                    if ((DateTime.Now - latestLifeSignal.CreationDate) >= MaxTimeDispatcherCanBeSilent)
                        throw new Exception("Dispatcher is already stopped.");
                }
                LatestLifeSignals[settings.DispatcherId.Value] = new LifeSignal
                {
                    SourceId = ComputationalUnit.Settings.DispatcherId.FromString("FirstChanceForLifeSignalNotReceived")
                };
            }

            var poisonPill = new PoisonPill
            {
                EffectOnCurrentWork = PoisonPillEffect.Cancel,
                DispatcherId = settings.DispatcherId
            };
            SendingBus.Send(poisonPill, settings.DispatcherId.PoisonPillSubscriptionId, StorageType.NonPersistent);
        }