/// <summary>
        /// Blocks execution of the current thread until the main window of the
        /// application is displayed or until the specified timeout interval elapses.
        /// </summary>
        /// <param name="timeout">The timeout interval.</param>
        public void WaitForMainWindow(TimeSpan timeout)
        {
            TimeSpan zero  = TimeSpan.FromMilliseconds(0);
            TimeSpan delta = TimeSpan.FromMilliseconds(10);

            while (!this.IsMainWindowOpened && timeout > zero)
            {
                if (settings.InProcessApplicationType == InProcessApplicationType.InProcessSameThread)
                {
                    DispatcherOperations.WaitFor(DispatcherPriority.ApplicationIdle);
                }
                else
                {
                    Thread.Sleep(10);
                }

                timeout -= delta;
            }

            // set as active
            if (settings.InProcessApplicationType == InProcessApplicationType.InProcessSameThread)
            {
                app.MainWindow.Activate();
            }
            else
            {
                this.DispatcherInvoke(() => { app.MainWindow.Activate(); });
            }
        }
        public override DispatcherOperation Create(DeterministicRandom random)
        {
            DispatcherPriority  priority  = ChooseValidPriority(PriorityValue);
            DispatcherOperation operation = null;

            switch (InvokeCallbackType)
            {
            case InvokeCallbackTypes.DispatcherOperationCallback:
                operation = Dispatcher.BeginInvoke(priority, new DispatcherOperationCallback(DispatcherOperationCallbackMethod), this);
                break;

            case InvokeCallbackTypes.SendOrPostCallback:
                operation = Dispatcher.BeginInvoke(priority, new SendOrPostCallback(SendOrPostMethod), this);
                break;

            case InvokeCallbackTypes.OneParamGeneric:
                operation = Dispatcher.BeginInvoke(priority, new OneParamGeneric(OneParamMethod), this);
                break;

            case InvokeCallbackTypes.TwoParamGeneric:
                operation = Dispatcher.BeginInvoke(priority, new TwoParamGeneric(TwoParamMethod), this, new object());
                break;

            case InvokeCallbackTypes.ThreeParamGeneric:
                operation = Dispatcher.BeginInvoke(priority, new ThreeParamGeneric(ThreeParamMethod), this, new object(), new object());
                break;

            case InvokeCallbackTypes.ZeroParamGeneric:
                operation = Dispatcher.BeginInvoke(priority, new ZeroParamGeneric(ZeroParamMethod));
                break;
            }

            operation.Aborted   += new EventHandler(OperationAborted);
            operation.Completed += new EventHandler(OperationCompleted);

            //Save the DispatcherOperation, Some combinations of actions need do on the same DispatcherOperation.
            lock (DispatcherOperations)
            {
                DispatcherOperations.Add(operation);
                if (DispatcherOperations.Count > 10)
                {
                    DispatcherOperations.RemoveAt(random.Next(DispatcherOperations.Count));
                }

                return(DispatcherOperations[random.Next(DispatcherOperations.Count)]);
            }
        }
        /// <summary>
        /// Closes the application
        /// </summary>
        public void Close()
        {
            if (app != null)
            {
                if (settings.InProcessApplicationType == InProcessApplicationType.InProcessSameThread)
                {
                    CloseHelper();

                    DispatcherOperations.WaitFor(DispatcherPriority.ApplicationIdle);
                    app.Shutdown();
                    app = null;
                }
                else
                {
                    DispatcherInvoke(() => { CloseHelper(); });

                    DispatcherOperations.WaitFor(DispatcherPriority.ApplicationIdle);
                    app.Dispatcher.InvokeShutdown();
                    app = null;
                }
            }
        }
        /// <summary>
        /// Waits for the given window to activate.
        /// </summary>
        /// <remarks>
        /// Note that this will not work for dialogs that block the thread.
        /// </remarks>
        /// <param name="windowName">The AutomationProperties.AutomationIdProperty value of the window</param>
        /// <param name="timeout">The timeout interval.</param>
        public void WaitForWindow(string windowName, TimeSpan timeout)
        {
            bool isWindowOpened = false;

            TimeSpan zero  = TimeSpan.FromMilliseconds(0);
            TimeSpan delta = TimeSpan.FromMilliseconds(10);

            while (!isWindowOpened && timeout > zero)
            {
                DispatcherOperations.WaitFor(TimeSpan.FromMilliseconds(100));
                timeout -= delta;

                if (settings.InProcessApplicationType == InProcessApplicationType.InProcessSameThread)
                {
                    isWindowOpened = WaitForWindowHelper(windowName);
                }
                else
                {
                    isWindowOpened = DispatcherInvoke <bool>(() => { return(WaitForWindowHelper(windowName)); });
                }
            }
        }