/// <summary></summary>
        public void Run(string[] args, Stoplight stoplight = null)
        {
            _commandLoaded = new ManualResetEvent(false);
            _stoplight     = stoplight ?? new Stoplight();

            new Thread(() => RunOnThread(args, _stoplight)).Start();

            _commandLoaded.WaitOne();
            if (Environment.UserInteractive)
            {
                ConsoleReader.Watch(
                    _stoplight,
                    CanBeStopped, CanBePaused,
                    Stop, Pause, Resume);
            }
        }
        private void RunOnThread(string[] args, Stoplight stoplight)
        {
            DateTime started   = Config.NowDelegate();
            var      stopwatch = Stopwatch.StartNew();

            Log.InfoFormat("Running: {0}", args.IsNullOrEmpty() ? "{null}" : string.Join(" ", args));
            if (Config.ConsoleMode.ArgumentsInterceptor != null)
            {
                var modifiedArgs = Config.ConsoleMode.ArgumentsInterceptor(args);
                if (!args.SequenceEqual(modifiedArgs))
                {
                    args = modifiedArgs;
                    Log.InfoFormat("Running modified args: {0}", string.Join(" ", args));
                }
            }

            IDisposable cleanup = null;

            if (Config.ConsoleMode.OnWrapRunCommand != null)
            {
                Log.Info("call OnWrapRunCommand");
                cleanup = Config.ConsoleMode.OnWrapRunCommand();
            }

            try
            {
                //load command after OnWrapRunCommand to let DI containers be configured
                _runData = _consoleCommandRepository.LoadCommand(args);

                if (Config.ConsoleMode.OnBeginRunCommand != null)
                {
                    Log.Info("call OnBeginRunCommand");
                    Config.ConsoleMode.OnBeginRunCommand(_runData.Command);
                }

                if (_runData.Errors.Any())
                {
                    foreach (var error in _runData.Errors)
                    {
                        Writer.WriteLines("", "!!!", error, "");
                    }
                }

                _runData.Command.SetServiceOnPropertyOrField((IStoplight)stoplight);

                _commandLoaded.Set();
                Log.Info("command loaded");

                //TODO: exclude console command
                if (CanBeStopped)
                {
                    Log.Info("CanBeStopped: subscribe unhandled exceptions and cancel key press");
                    AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
                    Console.CancelKeyPress += OnCancelKeyPress;
                }

                RunSafely(_runData);

                if (CanBeStopped)
                {
                    Log.Info("CanBeStopped: unsubscribe unhandled exceptions and cancel key press");
                    Console.CancelKeyPress -= OnCancelKeyPress;
                    AppDomain.CurrentDomain.UnhandledException -= OnUnhandledException;
                }
            }
            finally
            {
                if (cleanup != null)
                {
                    Log.Info("dispose OnWrapRunCommand");
                    cleanup.Dispose();
                }
            }

            if (Config.ConsoleMode.OnEndRunCommand != null)
            {
                Log.Info("call OnEndRunCommand");
                Config.ConsoleMode.OnEndRunCommand(new RunTime
                {
                    Elapsed   = stopwatch.Elapsed,
                    StartedOn = started,
                    EndedOn   = Config.NowDelegate()
                });
            }

            var runTimeMsg = string.Format("Command execution took:{0} started:{1} ended:{2}",
                                           stopwatch.Elapsed,
                                           started.ToString("hh:mm:ss"),
                                           Config.NowDelegate().ToString("hh:mm:ss"));

            if (!(_runData.Command is HelpCommand) &&
                !(_runData.Command is ViewArgsCommand))
            {
                if (Config.WriteRunTimeToConsole)
                {
                    Writer.WriteLine(runTimeMsg);
                }
                else
                {
                    Log.InfoFormat(runTimeMsg);
                }
            }

            stoplight.Stop();
        }