Come implementare un gestore di eccezioni “catch’em all” con curriculum?

Mi chiedo come posso scrivere un catch’em tutto il gestore di eccezioni nel livello dell’applicazione che darà all’utente la possibilità di riprendere il stream dell’applicazione?

Se si esegue un’applicazione Windows Form: aggiungere un gestore all’evento Application.ThreadException .

Presumo che tu stia scrivendo un’applicazione Windows, nel qual caso, , puoi farlo. Lascerò i diritti e i torti se devi o meno agli altri. Ci sono già abbastanza risposte che guardano questo e io suggerisco di considerarle attentamente prima di farlo effettivamente .

Si noti che questo codice si comporterà in modo diverso nel debugger di quanto non faccia se si esegue direttamente l’applicazione (un altro motivo per non farlo forse). Per far sì che l’applicazione mostri la messagebox e per continuare da quel momento in poi dovrai eseguire l’applicazione da explorer, non da Visual Studio.

Creare una nuova applicazione di moduli Windows. Il codice in Program.cs assomiglia a questo:

 using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Windows.Forms; namespace WindowsFormsApplication2 { static class Program { ///  /// The main entry point for the application. ///  [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Form1 form1 = new Form1(); Application.ThreadException += new ThreadExceptionEventHandler(form1.UnhandledThreadExceptionHandler); Application.Run(form1); } } } 

Quindi rendere il codice in Form1 assomiglia a qualcosa di simile:

 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"); } } } 

(Aggiungi il pulsante 1 al modulo e collegalo a button1_Click.)

Dipende da cosa intendi per “riprendere”. Il problema con le eccezioni è che, a meno che tu non stia molto attento, nel momento in cui si verifica un’eccezione, lo stato dell’applicazione è probabilmente corrotto: potresti aver completato la metà di un’operazione.

Se puoi isolare le tue operazioni – proprio come un database isola le transazioni – allora puoi effettivamente lasciare che il tuo utente riprenda dall’ultimo punto di commit. Ciò dipenderà molto dal tipo di applicazione. Potresti fornirci maggiori dettagli sul tipo di applicazione che stai costruendo?

Usa sotto il codice nella tua class program.cs. Invierà automaticamente la posta quando si verifica un’eccezione.

 using System; using System.Windows.Forms; using System.Net; using System.Net.Mail; using System.Threading; namespace ExceptionHandlerTest { static class Program { ///  /// The main entry point for the application. ///  [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); } } } } 

Non penso che questo sia realmente fattibile usando un gestore di errori globale. Devi capire quale tipo di errori sono recuperabili in diversi punti della tua applicazione e scrivere specifici gestori di errori per indirizzare gli errori nel momento in cui si verificano – a meno che tu non voglia ricorrere al riavvio dell’applicazione, che potrebbe funzionare o meno a seconda di cosa l’errore attuale è. Per fare qualsiasi tipo di curriculum, dovrai salvare uno stato sufficiente per ricominciare da uno stato buono noto.

È necessario leggere tutti i problemi associati allo stile di gestione degli errori ” On Error Resume Next ” di VB. Sembra che tu stia cercando di implementarlo per C #.

Anche se è ansible riprendere dal punto in cui viene generata l’eccezione, si tratta di una tecnica non funzionante per la gestione degli errori. Non c’è modo per un gestore globale di essere in grado di gestire qualsiasi errore / eccezione – non può sapere cosa è richiesto per qualsiasi situazione arbitraria.

Dovresti impostare una sorta di variabile globale e fare in modo che il codice della linea principale controlli continuamente le indicazioni di errore (ad esempio, usa la tecnica VB).

Penso che il meglio che puoi fare per recuperare da un errore come quello che stai descrivendo sia quello di catturare l’eccezione a livello di applicazione, registrare il problema, informare l’utente (e potenzialmente generare / inviare una sorta di rapporto sui problemi per te), e riavviare l’applicazione. Ovviamente, se si avvicina l’eccezione all’area del problema, il gestore ha la possibilità di fare qualcosa di un po ‘più intelligente, quindi non si deve fare affidamento sul gestore a livello di app come una stampella – proprio come un fail-safe.

In alcune versioni di .NET puoi effettivamente mettere un catcher su Application.Run () (lo troverai in program.cs) e questo dovrebbe catturare tutte le eccezioni del Main Thread, tuttavia nella maggior parte dei casi questo potrebbe essere un design scarso e non dare molte delle opportunità per “riprendere”. Inoltre dovrai sempre gestire manualmente eventuali eccezioni sui thread in background.

È ansible progettare un’applicazione per “catturare tutto” e visualizzare un messaggio di errore e informazioni di debug comuni, questo va bene fintanto che si esce in seguito. Ciò che è altamente scoraggiato è rendere un “curriculum” disponibile per l’utente, poiché questo probabilmente ti darà più problemi nel lungo periodo.

Questo fa solo urlare un cattivo design dappertutto. Non usare mai eccezioni per cose come questa. Le eccezioni devono essere utilizzate SOLO quando qualcosa che il programmatore non ha intenzione di accadere.

Se vuoi la gestione degli errori. non usare eccezioni come questa, rahter crea un sistema in cui si salvano stati e si può tornare agli stati ecc … ma usando le eccezioni per la gestione dello stato, idea sbagliata.

Il blocco di applicazioni di gestione delle eccezioni di Microsoft Enterprise Library contiene esempi di come farlo.

Fondamentalmente si circonda il codice che può generare eccezioni con questo:

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

Quindi è ansible configurare la politica per mostrare una finestra di dialogo all’utente e chiedere se vuole continuare.

Devi ancora provare a catturare blocchi nel codice nei punti in cui ritieni di essere in uno stato coerente.