private void AddError(bool canContinue, string errorMsg, object ex, bool terminateTimerEnabled) { try { if (!canContinue) { SetCanContinue(false); } if (terminateTimerEnabled) { EnableTerminateTimer(); } ErrorInfo ei = new ErrorInfo(); ei.ErrorMessage = errorMsg; ei.DetailsObject = ex; nextErrors.Enqueue(ei); nextButton.Text = FL.AppErrorDialogNext + " (" + nextErrors.Count + ")"; nextButton.Visible = true; } catch (Exception ex2) { FL.Critical(ex2, "FieldLog.Showing AppErrorDialog", false); FL.Flush(); MessageBox.Show( "Error updating the application error dialog. Details should be logged.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <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); } }