Подтвердить что ты не робот

Как реализовать один обработчик исключений "catch'em all" с резюме?

Интересно, как я могу написать обработчик исключений catch'em all на уровне приложения, который даст пользователю возможность возобновить поток приложений?

4b9b3361

Ответ 1

Если вы используете приложение Windows Forms: добавьте обработчик к событию Application.ThreadException.

Ответ 2

Я предполагаю, что вы пишете приложение Windows, и в этом случае да вы можете это сделать. Я оставлю права и заблуждения о том, должны ли вы другим. Есть уже достаточно ответов, которые смотрят на это, и я предлагаю вам рассмотреть их внимательно, прежде чем вы это сделаете.

Обратите внимание, что этот код будет вести себя по-разному в отладчике, чем при запуске приложения напрямую (по другой причине это не возможно). Чтобы приложение отображало сообщение и продолжалось после этого, вам нужно будет запустить приложение из проводника, а не из визуальной студии.

Создайте новое приложение форм Windows. Код в Program.cs выглядит примерно так:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2 {
    static class Program {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Form1 form1 = new Form1();
            Application.ThreadException += new ThreadExceptionEventHandler(form1.UnhandledThreadExceptionHandler);
            Application.Run(form1);
        }
    }
}

Затем сделайте код в Form1 выглядеть примерно так:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication2 {
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        public void UnhandledThreadExceptionHandler(object sender, ThreadExceptionEventArgs e) {
            this.HandleUnhandledException(e.Exception);
        }

        public void HandleUnhandledException(Exception e) {
            // do what you want here.
            if (MessageBox.Show("An unexpected error has occurred. Continue?",
                "My application", MessageBoxButtons.YesNo, MessageBoxIcon.Stop,
                MessageBoxDefaultButton.Button2) == DialogResult.No) {
                Application.Exit();
            }
        }

        private void button1_Click(object sender, EventArgs e) {
            throw new ApplicationException("Exception");
        }

    }
}

(добавьте кнопку 1 в форму и прикрепите ее кнопкой1_Щелкните.)

Ответ 3

Это зависит от того, что вы подразумеваете под "резюме". Проблема с исключениями заключается в том, что, если вы не будете очень осторожны, к тому времени, когда произойдет исключение, ваше состояние приложения вполне возможно повреждено - возможно, вы выполнили половину операции.

Если вы можете изолировать свои операции - так же, как база данных изолирует транзакции, то вы можете эффективно возобновить работу своего пользователя с "последней точки фиксации". Это будет очень сильно зависеть от типа вашего приложения. Не могли бы вы дать нам более подробную информацию о том, какое приложение вы создаете?

Ответ 4

Используйте код ниже в вашем классе program.cs. Он автоматически отправит почту при возникновении исключения.

using System;
using System.Windows.Forms;
using System.Net;
using System.Net.Mail;
using System.Threading; 

namespace ExceptionHandlerTest
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.ThreadException +=
                new ThreadExceptionEventHandler(Application_ThreadException);

            // Your designer generated commands.
        }

        static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) 
        {

            var fromAddress = new MailAddress("your Gmail address", "Your name");
            var toAddress = new MailAddress("email address where you want to receive reports", "Your name");
            const string fromPassword = "your password";
            const string subject = "exception report";
            Exception exception = e.Exception;
            string body = exception.Message + "\n" + exception.Data + "\n" + exception.StackTrace + "\n" + exception.Source;

            var smtp = new SmtpClient
            {
                Host = "smtp.gmail.com",
                Port = 587,
                EnableSsl = true,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
            };
            using (var message = new MailMessage(fromAddress, toAddress)
            {
                Subject = subject,
                Body = body
            })
            {
                //You can also use SendAsync method instead of Send so your application begin invoking instead of waiting for send mail to complete. SendAsync(MailMessage, Object) :- Sends the specified e-mail message to an SMTP server for delivery. This method does not block the calling thread and allows the caller to pass an object to the method that is invoked when the operation completes. 
                smtp.Send(message);
            }
        }
    }
}

Ответ 5

Я не думаю, что это действительно возможно с помощью глобального обработчика ошибок. Вам нужно выяснить, какие ошибки можно восстановить в разных точках вашего приложения и написать конкретные обработчики ошибок для устранения ошибок по мере их возникновения - если вы не хотите прибегать к перезапуску приложения, которое может работать или не работать в зависимости от того, что фактическая ошибка. Чтобы сделать какое-либо резюме, вам нужно будет сохранить достаточное количество состояний для перезапуска из известного хорошего состояния.

Ответ 6

В некоторых версиях .NET вы можете поместить зрелище вокруг Application.Run() (вы найдете это в program.cs), и это должно поймать все исключения Main Thread, но в большинстве случаев это может быть плохой дизайн и не даст вам большой возможности "возобновить". Кроме того, вам всегда придется вручную обрабатывать исключения из фоновых потоков.

Вы можете создать приложение для "уловить все" и отобразить общее сообщение об ошибке и отладочную информацию, это нормально, пока вы выходите из него. Что крайне не рекомендуется, так это сделать "резюме" доступным для пользователя, так как это, вероятно, даст вам больше проблем в долгосрочной перспективе.

Ответ 7

Вы должны прочитать все проблемы, связанные с стилем обработки ошибок VB "On Error Resume Next". Похоже, вы пытаетесь реализовать это для С#.

Даже если вы можете возобновить работу с того места, где генерируется исключение, это испорченный метод обработки ошибок. Нет никакого способа, чтобы глобальный обработчик действительно мог обрабатывать любую ошибку/исключение - он не может знать, что требуется для любой произвольной ситуации.

Вам нужно будет установить какую-то глобальную переменную, и код магистрали постоянно проверяет ее на наличие ошибок (т.е. использует технику VB).

Я думаю, что лучшее, что вы можете сделать, чтобы исправить ошибку, как вы описываете, - это поймать исключение на уровне приложения, зарегистрировать проблему, сообщить пользователю (и потенциально генерировать/отправлять какой-то отчет о проблеме для вас ) и перезапустите приложение. Конечно, если вы поймаете исключение ближе к проблемной области, у этого обработчика есть шанс сделать что-то более интеллектуальное, поэтому вы не должны полагаться на обработчика уровня приложения в качестве костыля - как на отказоустойчивость.

Ответ 8

Это просто кричит плохой дизайн на всем протяжении. Никогда не используйте исключения для таких вещей. Исключения являются ТОЛЬКО для использования, когда программист не намеревался произойти.

Если вам нужна обработка ошибок. не используйте исключения, подобные этому, rahter строит систему, в которой вы сохраняете состояния и можете вернуться к состояниям и т.д.... но используя исключения для обработки состояния, плохая идея.

Ответ 9

Блок приложений для обработки исключений Microsoft Enterprise Library содержит примеры того, как вы можете это сделать.

В основном вы окружаете код, который может генерировать исключения:

try
{
  MyMethodThatMightThrow();
}
catch(Exception ex)
{
   bool rethrow = ExceptionPolicy.HandleException(ex, "SomePolicy");
   if (rethrow) throw;
}

Затем вы можете настроить политику, чтобы показать пользователю диалог и спросить, хочет ли она продолжить.

Вам все равно нужно помещать блоки try catch в свой код в точках, где вы считаете, что находитесь в согласованном состоянии.