Exemplo n.º 1
0
        private static void UiThreadStart()
        {
            // Keep the window in the foreground.
            // Sometimes, when debugging in Visual Studio, the window sits in the background,
            // unnoticed, and prevents the application to shut down because it's not a background
            // thread. Setting TopMost again after a short while helps to bring it in the foreground
            // again.
            System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
            timer.Tick += delegate(object sender, EventArgs args)
            {
                // Just to be sure, also set Visible, it doesn't hurt
                currentInstance.Visible = true;
                currentInstance.TopMost = true;

                // Come back, but not so soon
                timer.Interval *= 2;
            };
            timer.Interval = 100;
            timer.Start();

            Application.Run(currentInstance);

            // The window has been closed and the message loop was left. Should there still be a
            // timer event scheduled, it won't be executed anymore. Now clean up everything.
            timer.Stop();
            timer.Dispose();
            lock (syncLock)
            {
                currentInstance.Dispose();
                currentInstance = null;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Shows the application error dialog. This is the only method that is called to show or
        /// update an error dialog. If a dialog is already open, the error is added to it.
        /// </summary>
        /// <param name="canContinue">Indicates whether the application can continue.</param>
        /// <param name="errorMsg">The error message to display.</param>
        /// <param name="ex">The <see cref="Exception"/> instance to display as details object.</param>
        /// <param name="terminateTimerEnabled">Indicates whether the termination safety timer has been started.</param>
        public static void ShowError(bool canContinue, string errorMsg, object ex, bool terminateTimerEnabled)
        {
            lock (syncLock)
            {
                try
                {
                    if (currentInstance == null)
                    {
                        currentInstance = new AppErrorDialog();
                        currentInstance.SetCanContinue(canContinue);
                        currentInstance.errorLabel.Text      = errorMsg;
                        currentInstance.grid.SelectedObject  = ex;
                        currentInstance.detailsLabel.Enabled = ex != null;
                        if (terminateTimerEnabled)
                        {
                            currentInstance.EnableTerminateTimer();
                        }

                        // Source: http://stackoverflow.com/a/3992635/143684
                        uiThread      = new Thread(UiThreadStart);
                        uiThread.Name = "FieldLog.AppErrorDialogUIThread";
                        uiThread.SetApartmentState(ApartmentState.STA);
                        uiThread.Start();
                    }
                    else
                    {
                        // Add next error to existing dialog
                        // Wait until the window handle is created
                        int count = 0;
                        while (!currentInstance.IsHandleCreated)
                        {
                            if (count++ > 500)
                            {
                                throw new TimeoutException("Application error dialog was not created in reasonable time.");
                            }
                            Thread.Sleep(10);
                        }
                        currentInstance.Invoke(new AddErrorDelegate(currentInstance.AddError), canContinue, errorMsg, ex, terminateTimerEnabled);
                    }
                }
                catch (Exception ex2)
                {
                    FL.Critical(ex2, "FieldLog.Showing AppErrorDialog", false);
                    FL.Flush();
                    MessageBox.Show(
                        "Error showing the application error dialog. Details should be logged.",
                        "Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                }
            }

            // Make sure we won't continue in this thread if it's not possible
            while (!canContinue)
            {
                Thread.Sleep(1000000);
            }

            // Slow down or halt the application as long as there are many pending errors.
            // The error dialog runs in its own thread so it will still respond to user input. :-)
            // (Unless, of course, should an error occur in the error dialog…)
            if (currentInstance != null && currentInstance.GetNextErrorsCount() >= 20)
            {
                Thread.Sleep(1000);
            }
            while (currentInstance != null && currentInstance.GetNextErrorsCount() >= 40)
            {
                Thread.Sleep(1000);
            }
        }
Exemplo n.º 3
0
        private static void UiThreadStart()
        {
            // Keep the window in the foreground.
            // Sometimes, when debugging in Visual Studio, the window sits in the background,
            // unnoticed, and prevents the application to shut down because it's not a background
            // thread. Setting TopMost again after a short while helps to bring it in the foreground
            // again.
            System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
            timer.Tick += delegate (object sender, EventArgs args)
                {
                    // Just to be sure, also set Visible, it doesn't hurt
                    currentInstance.Visible = true;
                    currentInstance.TopMost = true;

                    // Come back, but not so soon
                    timer.Interval *= 2;
                };
            timer.Interval = 100;
            timer.Start();

            Application.Run(currentInstance);

            // The window has been closed and the message loop was left. Should there still be a
            // timer event scheduled, it won't be executed anymore. Now clean up everything.
            timer.Stop();
            timer.Dispose();
            lock (syncLock)
            {
                currentInstance.Dispose();
                currentInstance = null;
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Shows the application error dialog. This is the only method that is called to show or
        /// update an error dialog. If a dialog is already open, the error is added to it.
        /// </summary>
        /// <param name="canContinue">Indicates whether the application can continue.</param>
        /// <param name="errorMsg">The error message to display.</param>
        /// <param name="ex">The <see cref="Exception"/> instance to display as details object.</param>
        /// <param name="terminateTimerEnabled">Indicates whether the termination safety timer has been started.</param>
        public static void ShowError(bool canContinue, string errorMsg, object ex, bool terminateTimerEnabled)
        {
            lock (syncLock)
            {
                try
                {
                    if (currentInstance == null)
                    {
                        currentInstance = new AppErrorDialog();
                        currentInstance.SetCanContinue(canContinue);
                        currentInstance.errorLabel.Text = errorMsg;
                        currentInstance.grid.SelectedObject = ex;
                        currentInstance.detailsLabel.Enabled = ex != null;
                        if (terminateTimerEnabled)
                        {
                            currentInstance.EnableTerminateTimer();
                        }

                        // Source: http://stackoverflow.com/a/3992635/143684
                        uiThread = new Thread(UiThreadStart);
                        uiThread.Name = "FieldLog.AppErrorDialogUIThread";
                        uiThread.SetApartmentState(ApartmentState.STA);
                        uiThread.Start();
                    }
                    else
                    {
                        // Add next error to existing dialog
                        // Wait until the window handle is created
                        int count = 0;
                        while (!currentInstance.IsHandleCreated)
                        {
                            if (count++ > 500)
                                throw new TimeoutException("Application error dialog was not created in reasonable time.");
                            Thread.Sleep(10);
                        }
                        currentInstance.Invoke(new AddErrorDelegate(currentInstance.AddError), canContinue, errorMsg, ex, terminateTimerEnabled);
                    }
                }
                catch (Exception ex2)
                {
                    FL.Critical(ex2, "FieldLog.Showing AppErrorDialog", false);
                    FL.Flush();
                    MessageBox.Show(
                        "Error showing the application error dialog. Details should be logged.",
                        "Error",
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                }
            }

            // Make sure we won't continue in this thread if it's not possible
            while (!canContinue)
            {
                Thread.Sleep(1000000);
            }

            // Slow down or halt the application as long as there are many pending errors.
            // The error dialog runs in its own thread so it will still respond to user input. :-)
            // (Unless, of course, should an error occur in the error dialog…)
            if (currentInstance != null && currentInstance.GetNextErrorsCount() >= 20)
            {
                Thread.Sleep(1000);
            }
            while (currentInstance != null && currentInstance.GetNextErrorsCount() >= 40)
            {
                Thread.Sleep(1000);
            }
        }