private async Task RunSimulatorAsync()
        {
            btnStart.IsEnabled = false;
            btnStop.IsEnabled = true;
            btnLoad.IsEnabled = false;
            if (quickActionButtons != null)
                foreach (var bt in quickActionButtons)
                    bt.IsEnabled = false;


            // Run the simulator in another task so it is not executed in the GUI thread.
            // However, we then await that new task so we are notified when it is finished.
            Simulator sim = simulator = new Simulator(currentQuickAction != null ? currentQuickAction.Action 
                : project.Configuration.MainAction, TTRWindowsEnvironment.Instance);
            sim.AsyncRetryHandler = async (ex) => !closeWindowAfterStop && await HandleSimulatorRetryAsync(sim, ex);

            Exception runException = null;
            simulatorStartAction?.Invoke();
            await Task.Run(async () =>
            {
                try
                {
                    await sim.RunAsync();
                }
                catch (Exception ex)
                {
                    runException = ex;   
                }
            });
            simulatorStopAction?.Invoke();

            // Don't show a messagebox if we need to close the window.
            if (!closeWindowAfterStop && runException != null && !(runException is SimulatorCanceledException))
            {
                TaskDialog dialog = new TaskDialog()
                {
                    Title = AppName,
                    MainInstruction = "Simulator stopped!",
                    Content = runException.Message,
                    ExpandedInformation = GetExceptionDetailsText(runException),
                    MainIcon = TaskDialog.TaskDialogIcon.Stop,
                    CommonButtons = TaskDialog.TaskDialogButtons.OK
                };
                dialog.Flags |= TaskDialog.TaskDialogFlags.ExpandFooterArea;
                dialog.Show(this);
            }

            HandleSimulatorCanceled();
        }
        private void HandleSimulatorCanceled()
        {
            simulator = null;
            btnStart.IsEnabled = true;
            btnStop.IsEnabled = false;
            btnLoad.IsEnabled = true;
            if (quickActionButtons != null)
                foreach (var bt in quickActionButtons)
                    bt.IsEnabled = true;

            if (currentQuickAction != null)
            {
                currentQuickAction = null;
                RefreshProjectControls();
            }

            if (closeWindowAfterStop)
                Close();
        }
        private async void StartSimulator()
        {
            btnStart.IsEnabled = false;
            btnStop.IsEnabled = true;
            btnLoad.IsEnabled = false;


            // Run the simulator in another task so it is not executed in the GUI thread.
            // However, we then await that new task so we are notified when it is finished.
            Simulator sim = simulator = new Simulator(project.Configuration, TTRWindowsEnvironment.Instance);

            Exception runException = null;
            if (simulatorStartAction != null)
                simulatorStartAction();
            await Task.Run(async () =>
            {
                try
                {
                    await sim.RunAsync();
                }
                catch (Exception ex)
                {
                    runException = ex;   
                }
            });
            if (simulatorStopAction != null)
                simulatorStopAction();

            // Don't show a messagebox if we need to close the window.
            if (!closeWindowAfterStop && runException != null && !(runException is SimulatorCanceledException))
                MessageBox.Show(this, runException.Message, "Simulator stopped!", MessageBoxButton.OK, MessageBoxImage.Warning);

            HandleSimulatorCanceled();
        }
        private async Task<bool> HandleSimulatorRetryAsync(Simulator sim, ExceptionDispatchInfo ex)
        {
            // Show a TaskDialog.
            bool result = false;
            await Dispatcher.InvokeAsync(new Action(() =>
            {
                if (!closeWindowAfterStop)
                {
                    TaskDialog dialog = new TaskDialog()
                    {
                        Title = AppName,
                        MainInstruction = "Simulator interrupted!",
                        Content = ex.SourceException.Message,
                        ExpandedInformation = GetExceptionDetailsText(ex.SourceException),
                        MainIcon = TaskDialog.TaskDialogIcon.Warning,
                        CommonButtons = TaskDialog.TaskDialogButtons.Cancel
                    };
                    dialog.Flags |= TaskDialog.TaskDialogFlags.UseCommandLinks |
                            TaskDialog.TaskDialogFlags.ExpandFooterArea;

                    var buttonTryAgain = dialog.CreateCustomButton("Try again\n" 
                        + "The Simulator will try to run the current action again.");
                    var buttonStop = dialog.CreateCustomButton("Stop the Simulator");

                    dialog.CustomButtons = new TaskDialog.ICustomButton[] { buttonTryAgain, buttonStop };
                    dialog.DefaultCustomButton = buttonStop;

                    dialog.Show(this);

                    if (dialog.ResultCustomButton == buttonTryAgain)
                        result = true;
                }
            }));

            return result;
        }
        private void HandleSimulatorCanceled()
        {
            simulator = null;
            btnStart.IsEnabled = true;
            btnStop.IsEnabled = false;
            btnLoad.IsEnabled = true;

            if (closeWindowAfterStop)
                Close();
        }