2009-08-19 45 views
6

Điều này liên quan đến một số previous question.Tại sao ngoại lệ AppDomain luôn kết thúc ứng dụng?

Những gì tôi đang cố gắng hiểu bây giờ là làm thế nào đến trường hợp ngoại lệ thread UI có thể được ngăn chặn từ chấm dứt ứng dụng trong khi không ngoại lệ UI không thể được.

Để tham khảo, hãy xem this example.

Quan trọng nhất, những gì tôi muốn có thể làm trong trường hợp đó là "âm thầm" chấm dứt quá trình - mà không hiển thị hộp thoại Windows hỏi tôi có muốn gửi báo cáo lỗi hay không.

Đây là AppDomain UnhandledExceptionHandler tôi:

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
{    
    try 
    { 
     // Maybe do some logging here if allowed 
    } 
    catch 
    { 
    } 

    // then just terminate the application 
    Application.Exit();    
} 

CẬP NHẬT
Trong ánh sáng của bình luận trong this answer, tôi muốn làm rõ rằng điều quan trọng nhất mà tôi muốn tìm hiểu thêm về các cơ chế cho phép chuỗi giao diện người dùng có cơ hội sớm để nắm bắt ngoại lệ không được xử lý thông qua cơ chế Application.ThreadException. Và liệu hành vi đó có thể được triển khai trên một chuỗi không phải UI hay không.

Trả lời

7

Vì vậy, sau khi thực hiện thêm một số tìm kiếm trên Google, tôi đã tìm thấy giải thích rất thú vị này được đưa ra cùng một vấn đề như được mô tả bởi Jeff Atwood on his blog.

Xin chào tất cả, Xin lỗi vì sự nhầm lẫn. Hành vi này thực sự là thiết kế, mặc dù thiết kế có thể được một chút phức tạp ở lần.

Điều đầu tiên cần hiểu là sự kiện UnhandledException không phải là một ngoại lệ không xử lý "trình xử lý". Đăng ký sự kiện, trái với những gì tài liệu nói :-(, không gây ra các ngoại lệ chưa xử lý được xử lý (Kể từ đó chúng sẽ không được giải quyết, nhưng tôi sẽ dừng lại với lý do tròn đã ...) sự kiện UnhandledException chỉ đơn giản thông báo cho bạn rằng một ngoại lệ đã đi unhandled, trong trường hợp bạn muốn cố gắng tiết kiệm nhà nước trước khi chủ đề hay ứng dụng chết. FWIW của bạn, tôi đã nộp một lỗi để có được những tài liệu cố định.

Chỉ cần để những điều phức tạp, trong v1.0 và 1.1, một ngoại lệ chưa được giải quyết không phải lúc nào cũng có nghĩa là ứng dụng của bạn sẽ chết. Nếu ngoại lệ chưa được xử lý xảy ra trên bất kỳ thứ gì ngoài chủ đề chính hoặc chuỗi đã bắt đầu cuộc sống của nó trong mã không được quản lý, CLR đã khắc phục ngoại lệ và cho phép ứng dụng của bạn tiếp tục. Điều này thường là điều ác, bởi vì điều thường xảy ra là, ví dụ, các luồng ThreadPool sẽ âm thầm chết đi, từng cái một, cho đến khi ứng dụng của bạn không thực sự làm bất kỳ công việc nào. Tìm ra nguyên nhân của loại thất bại này gần như là không thể. Điều này có thể là lý do tại sao Jeff nghĩ rằng nó đã làm việc trước đây ... ông chỉ luôn luôn nhìn thấy tai nạn trên các chủ đề không chính.

Trong v2.0, một ngoại lệ chưa được giải quyết trên bất kỳ chuỗi nào sẽ gỡ ứng dụng xuống. Chúng tôi đã nhận thấy rằng việc gỡ lỗi các sự cố dễ dàng hơn rất nhiều so với việc gỡ lỗi treo hoặc sự cố ngừng hoạt động im lặng được mô tả ở trên.

BTW, trên máy 1.1 của tôi, ví dụ từ MSDN không có đầu ra mong muốn; nó chỉ là dòng thứ hai không hiển thị cho đến khi bạn đã đính kèm một trình gỡ rối (hay không). Trong v2, chúng tôi đã lật những thứ xung quanh để sự kiện UnhandledException kích hoạt trước khi trình gỡ lỗi đính kèm, dường như điều mà hầu hết mọi người mong đợi.

Jonathan Keljo Exceptions CLR PM Jonathan Keljo trên 18 Tháng Hai 2005 22:02

Tuy nhiên, tôi vẫn quan tâm đến cách thread UI hoàn thành các trick của cho phép bạn có một nắm bắt xử lý-tất cả cho tất cả các ngoại lệ của chuỗi giao diện người dùng.

Thậm chí nhiều hơn, Tôi rất quan tâm đến việc một cách để vô hiệu hóa các NET JIT Debugging Dialog cho ứng dụng của tôi chỉ (không disabling it for the whole machine as seen here)

3

Nó không phải là bất kỳ ngoại lệ AppDomain chấm dứt ứng dụng, đó là ngoại lệ unhandled (của bất kỳ loại) sẽ xé xuống AppDomain và chấm dứt ứng dụng.

Vấn đề ở đây là bạn có thể xử lý ngoại lệ cho chuỗi giao diện người dùng một cách rõ ràng, ở mức khá cao. Tuy nhiên, khi bạn có một ngoại lệ chưa được giải quyết trong một chủ đề nền, không có phương tiện để xử lý nó dễ dàng ở cùng một mức độ, vì vậy nó có xu hướng truyền bá và kéo xuống ứng dụng. Application.ThreadException cho phép bạn ít nhất biết rằng đây là những gì gây ra lỗi, và đăng nhập nó nếu cần thiết.

Các ngoại lệ chưa được xử lý trong chuỗi giao diện người dùng sẽ gây ra cùng một điều xảy ra.

+0

@Reed: "trường hợp ngoại lệ Unhandled trong thread UI sẽ gây ra cùng điều xảy ra. " - Đây không phải là sự thật. Vui lòng tạo một ứng dụng thử nghiệm và tự mình thử. –

+1

Về mặt kỹ thuật, tôi nên nói "Ngoại lệ không chính xác trên chuỗi chính". Windows Forms thêm hành vi xử lý ngoại lệ của riêng nó vào luồng giao diện người dùng (vì nó hoàn toàn chạy trên luồng giao diện người dùng) làm thay đổi hành vi của luồng chính. Tạo một ứng dụng giao diện điều khiển và thử điều này, và bạn sẽ thấy không có vấn đề gì xảy ra với chủ đề - tất cả chúng sẽ làm hỏng ứng dụng. –

+0

Sau đó, tôi nên restate câu hỏi của tôi: Làm thế nào để thread UI hoàn thành hành vi xử lý ngoại lệ chung của nó? Đó có phải là một cái gì đó tôi có thể sao chép như hành vi cho một chủ đề không phải UI? –

2

Điều này có giúp ích gì không?

Improved Unhandled Exception behavior in .NET 2.0

Ngoài ra, mã này dường như "chết lặng lẽ". Bạn đang tìm kiếm thứ gì khác phải không?

using System; 

namespace UnhandledException 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException; 

      throw new NotImplementedException(); 
     } 

     static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) 
     { 
      Exception exception = (Exception)e.ExceptionObject; 
      System.Console.WriteLine("exception=[" + exception.ToString() + "]"); 

      Environment.Exit(-1); 
     } 
    } 
} 
+0

Có nó .. Tôi vừa đọc xong bài đăng và nhận xét khi bạn đăng bài đó. 1 tuy nhiên .. –

+0

Có, Environemnt.Exit dường như thực hiện thủ thuật! Tôi sẽ để lại các câu hỏi mở trong một thời gian lâu hơn để xem liệu có ai có thể đưa ra một cái nhìn sâu sắc về cách mà chuỗi giao diện người dùng hoàn thành ngoại lệ bắt tất cả hay không. Nếu không, bạn sẽ có phiếu bầu của tôi cho câu trả lời được chấp nhận! –

+0

Application.ThreadException chỉ là một biến thể của một "xử lý ngoại lệ chưa xử lý". Có nhiều biến thể (Console App so với WinForms so với WebForms so với WCF, v.v.). Tôi không chắc tôi hiểu câu hỏi của bạn. Nói chung, tôi thực hiện mọi ứng dụng được áp dụng. –

Các vấn đề liên quan