Sự khác biệt giữa Application.ThreadException và AppDomain.CurrentDomain.UnhandledException là gì?


107

Được rồi, đây là một cái dễ dàng:

  • Sự khác biệt giữa Application.ThreadExceptionvà là
    AppDomain.CurrentDomain.UnhandledExceptiongì?

  • Tôi có cần phải xử lý cả hai không?

Cảm ơn!

Câu trả lời:


98

Application.ThreadException dành riêng cho Windows Forms. Winforms chạy các trình xử lý sự kiện để phản hồi các thông báo được Windows gửi tới nó. Sự kiện Click chẳng hạn, tôi chắc rằng bạn biết chúng. Nếu một trình xử lý sự kiện như vậy ném một ngoại lệ thì sẽ có một điểm dừng bên trong vòng lặp thông báo Winforms bắt ngoại lệ đó.

Backstop đó kích hoạt sự kiện Application.ThreadException . Nếu bạn không ghi đè nó, người dùng sẽ nhận được một ThreadExceptionDialog . Điều này cho phép anh ta bỏ qua ngoại lệ và tiếp tục chạy chương trình của bạn. Không phải là một ý tưởng tuyệt vời btw.

Bạn có thể vô hiệu hóa hành vi này bằng cách gọi Application.SetUnhandledExceptionMode () trong phương thức Main () trong Program.cs. Nếu không có backstop đó, điều thông thường sẽ xảy ra khi một chuỗi chết vì một ngoại lệ chưa được xử lý: AppDomain.UnhandledException kích hoạt và chương trình kết thúc.

Fwiw: "ThreadException" là một lựa chọn tên rất kém. Nó không liên quan gì đến chủ đề.


Và làm thế nào để ngăn chặn ứng dụng WinForms bị treo khi xảy ra Application.ThreadException. Tôi đã đặt ra một câu hỏi cho điều này [tại đây ] với mã C # nhỏ của tôi.
Mahesha999

2
Tôi luôn đọc nó là ngoại lệ của luồng ứng dụng, vì các biểu mẫu win được liên kết với một luồng duy nhất.
Gusdor

36

Từ nguồn :

Trong các ứng dụng sử dụng Biểu mẫu Windows, các ngoại lệ không được xử lý trong chuỗi ứng dụng chính gây ra Application.ThreadException sự kiện được nêu ra. Nếu sự kiện này được xử lý, hành vi mặc định là ngoại lệ được xử lý không kết thúc ứng dụng, mặc dù ứng dụng được để ở trạng thái không xác định. Trong trường hợp đó, UnhandledException sự kiện không được nêu ra. Hành vi này có thể được thay đổi bằng cách sử dụng tệp cấu hình ứng dụng hoặc bằng cách sử dụng Application.SetUnhandledExceptionModephương pháp để thay đổi chế độ thành UnhandledExceptionMode.ThrowExceptiontrước khi ThreadException trình xử lý sự kiện được kết nối. Điều này chỉ áp dụng cho chuỗi ứng dụng chính. Sự UnhandledException kiện được đưa ra cho các ngoại lệ chưa xử lý được ném trong các chuỗi khác.

Bắt đầu với Visual Studio 2005 , khung ứng dụng Visual Basic cung cấp một sự kiện khác cho các trường hợp ngoại lệ chưa được xử lý trong chuỗi ứng dụng chính - WindowsFormsApplicationBase.UnhandledException. Sự kiện này có một đối tượng đối số sự kiện trùng tên với đối tượng đối số sự kiện được AppDomain.UnhandledException sử dụng, nhưng có các thuộc tính khác nhau. Đặc biệt, đối tượng đối số sự kiện này có thuộc ExitApplicationtính cho phép ứng dụng tiếp tục chạy, bỏ qua ngoại lệ chưa xử lý (và để ứng dụng ở trạng thái không xác định). Trong trường hợp đó, sự kiện AppDomain.UnhandledException không được đưa ra.

Application.ThreadExceptioncó thể bị bắt và ứng dụng có thể tiếp tục (nói chung không phải là một ý tưởng tuyệt vời, nhưng đối với ứng dụng như chạy định kỳ một số hành động thì đây là một giải pháp tốt).

Để bắt các ngoại lệ xảy ra trong các luồng không được tạo và sở hữu bởi Windows Forms, hãy sử dụng AppDomain.UnhandledException. Nó cho phép ứng dụng ghi lại thông tin về ngoại lệ trước khi trình xử lý mặc định của hệ thống báo cáo ngoại lệ cho người dùng và kết thúc ứng dụng.
Việc xử lý ngoại lệ này không ngăn ứng dụng bị chấm dứt.
Tối đa có thể làm được (dữ liệu chương trình có thể bị hỏng khi không xử lý các ngoại lệ) là lưu dữ liệu chương trình để phục hồi sau này. Sau đó miền ứng dụng được dỡ bỏ và ứng dụng kết thúc.

Bắt đầu với .NET 4 , sự kiện này không được đưa ra cho các trường hợp ngoại lệ làm hỏng trạng thái của quá trình, chẳng hạn như tràn ngăn xếp hoặc vi phạm quyền truy cập, trừ khi trình xử lý sự kiện quan trọng về bảo mật và có HandleProcessCorruptedStateExceptionsAttribute thuộc tính.

Để biết thêm chi tiết, hãy xem MSDN .


18

OK - Tôi đã có nó trước mặt, đoạn mã này từ msdn khá dễ hiểu:

public static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new 
        ThreadExceptionEventHandler(ErrorHandlerForm.Form1_UIThreadException);

    // Set the unhandled exception mode to force all Windows Forms 
    // errors to go through our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event. 
    AppDomain.CurrentDomain.UnhandledException +=
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    // Runs the application.
    Application.Run(new ErrorHandlerForm());
}

3
điều này trái ngược với câu trả lời khác của serhio khi anh ấy nói: UnhandledExceptionMode.ThrowException nên được đặt trước khi trình xử lý sự kiện ThreadException được nối. Bạn không chắc chắn nếu lệnh thực sự quan trọng ...
Davide Piras

@DavidePiras vâng, và có điều gì đó âm u hơn. SetUnhandledException dường như không tạo ra sự khác biệt trong trường hợp của tôi.
nawfal

0

ThreadExceptionVấn đề là, xảy ra do sự cố với luồng của bạn, Unhandled Exceptionnó sẽ được kích hoạt nếu bạn ném một ngoại lệ không được xử lý.

Cách dễ dàng để gây ra lỗi thứ hai là tạo một ứng dụng mà không cần thử ... bắt khối và ném một ngoại lệ.

Bây giờ nếu bạn cần bảo hiểm, bạn có thể xử lý cả hai, tuy nhiên nếu bạn nắm bắt và xử lý exceptionschính xác thì bạn không cần người UnhandledExceptionxử lý vì nó giống như một bắt tất cả.


cảm ơn - những gì tôi đã không về quá rõ ràng là nếu xử lý UnhandledException tôi sẽ bắt cũng ThreadException - mà dường như không phải là trường hợp
JohnIdol
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.