Application.ThreadException และ AppDomain.CurrentDomain.UnhandledException แตกต่างกันอย่างไร


107

เอาล่ะนี่เป็นเรื่องง่าย:

  • อะไรคือความแตกต่างระหว่างApplication.ThreadExceptionและ
    AppDomain.CurrentDomain.UnhandledException?

  • ฉันจำเป็นต้องจัดการทั้งสองอย่างหรือไม่?

ขอบคุณ!

คำตอบ:


98

Application.ThreadException เฉพาะสำหรับ Windows Forms Winforms เรียกใช้ตัวจัดการเหตุการณ์เพื่อตอบสนองต่อข้อความที่ Windows ส่งมา ตัวอย่างเช่นเหตุการณ์คลิกฉันแน่ใจว่าคุณรู้จักพวกเขา หากตัวจัดการเหตุการณ์ดังกล่าวแสดงข้อยกเว้นแสดงว่ามีแบ็คสต็อปภายในลูปข้อความ Winforms ที่จับข้อยกเว้นนั้น

backstop นั้นทำให้เหตุการณ์Application.ThreadExceptionเริ่มทำงาน หากคุณไม่ได้แทนที่ผู้ใช้จะได้รับThreadExceptionDialog ซึ่งทำให้เขาไม่สนใจข้อยกเว้นและเรียกใช้โปรแกรมของคุณต่อไป ไม่ใช่ความคิดที่ดี btw.

คุณสามารถปิดใช้งานพฤติกรรมนี้ได้โดยเรียกApplication.SetUnhandledExceptionMode ()ในเมธอด Main () ใน Program.cs หากไม่มี backstop นั้นสิ่งปกติจะเกิดขึ้นเมื่อเธรดตายจากข้อยกเว้นที่ไม่สามารถจัดการได้: AppDomain.UnhandledException จะเริ่มทำงานและโปรแกรมจะหยุดทำงาน

Fwiw: "ThreadException" เป็นตัวเลือกชื่อที่แย่มาก ไม่มีอะไรเกี่ยวข้องกับเธรด


และวิธีหยุดแอปพลิเคชัน WinForms ไม่ให้หยุดทำงานเมื่อเกิดApplication.ThreadException. ฉันตั้งคำถามเกี่ยวกับเรื่องนี้[ที่นี่ ] พร้อมกับรหัส C # ขนาดเล็กของฉัน
Mahesha999

2
ฉันมักจะอ่านว่าเป็นข้อยกเว้นของเธรดแอปพลิเคชันเนื่องจาก winforms ถูกผูกไว้กับเธรดเดียว
Gusdor

36

จากแหล่งที่มา :

ในแอปพลิเคชันที่ใช้ Windows Forms ข้อยกเว้นที่ไม่ได้จัดการในเธรดแอ็พพลิเคชันหลักจะทำให้เกิดApplication.ThreadException เหตุการณ์ขึ้น หากเหตุการณ์นี้ได้รับการจัดการลักษณะการทำงานเริ่มต้นคือข้อยกเว้นที่ไม่สามารถจัดการได้จะไม่ยุติแอปพลิเคชันแม้ว่าแอปพลิเคชันจะอยู่ในสถานะที่ไม่รู้จัก ในกรณีนั้นUnhandledException เหตุการณ์จะไม่เกิดขึ้น พฤติกรรมนี้สามารถเปลี่ยนแปลงได้โดยใช้ไฟล์คอนฟิกูเรชันแอ็พพลิเคชันหรือโดยใช้ Application.SetUnhandledExceptionModeวิธีการเปลี่ยนโหมด UnhandledExceptionMode.ThrowExceptionก่อนที่ThreadException ตัวจัดการเหตุการณ์จะเชื่อมต่อ ใช้กับเธรดแอปพลิเคชันหลักเท่านั้น UnhandledException เหตุการณ์ถูกยกขึ้นเพื่อจัดการข้อยกเว้นโยนในหัวข้ออื่น ๆ

เริ่มต้นด้วยVisual Studio 2005ที่Visual Basicกรอบใบสมัครให้เหตุการณ์อื่นสำหรับข้อยกเว้นที่ไม่สามารถจัดการในหัวข้อการประยุกต์ใช้หลัก WindowsFormsApplicationBase.UnhandledException- เหตุการณ์นี้มีอ็อบเจ็กต์อาร์กิวเมนต์เหตุการณ์ที่มีชื่อเดียวกันกับอ็อบเจ็กต์อาร์กิวเมนต์เหตุการณ์ที่ใช้โดย AppDomain.UnhandledException แต่มีคุณสมบัติต่างกัน โดยเฉพาะอย่างยิ่งอ็อบเจ็กต์อาร์กิวเมนต์เหตุการณ์นี้มีExitApplicationคุณสมบัติที่อนุญาตให้แอปพลิเคชันทำงานต่อไปโดยไม่สนใจข้อยกเว้นที่ไม่สามารถจัดการได้ (และออกจากแอปพลิเคชันในสถานะที่ไม่รู้จัก) ในกรณีนั้นเหตุการณ์ AppDomain.UnhandledException จะไม่ถูกยกขึ้น

Application.ThreadExceptionสามารถจับได้และแอปพลิเคชันสามารถดำเนินการต่อได้ (โดยทั่วไปไม่ใช่ความคิดที่ดี แต่สำหรับแอปพลิเคชันเช่นการเรียกใช้การดำเนินการบางอย่างเป็นระยะ ๆ นี่เป็นทางออกที่ดี)

ในการตรวจจับข้อยกเว้นที่เกิดขึ้นในเธรดที่ไม่ได้สร้างและเป็นเจ้าของโดย Windows Forms ให้ใช้ไฟล์AppDomain.UnhandledException. อนุญาตให้แอปพลิเคชันบันทึกข้อมูลเกี่ยวกับข้อยกเว้นก่อนที่ตัวจัดการเริ่มต้นของระบบจะรายงานข้อยกเว้นไปยังผู้ใช้และยุติแอปพลิเคชัน
การจัดการข้อยกเว้นนี้ไม่ได้ป้องกันไม่ให้แอปพลิเคชันถูกยกเลิก
สูงสุดที่สามารถทำได้ (ข้อมูลโปรแกรมอาจเสียหายเมื่อไม่มีการจัดการข้อยกเว้น) คือการบันทึกข้อมูลโปรแกรมเพื่อการกู้คืนในภายหลัง หลังจากนั้นโดเมนของแอปพลิเคชันจะถูกยกเลิกการโหลดและแอปพลิเคชันจะสิ้นสุดลง

เริ่มต้นด้วย. NET 4เหตุการณ์นี้จะไม่ถูกยกขึ้นสำหรับข้อยกเว้นที่ทำให้สถานะของกระบวนการเสียหายเช่นสแต็กล้นหรือการละเมิดการเข้าถึงเว้นแต่ว่าตัวจัดการเหตุการณ์จะมีความสำคัญด้านความปลอดภัยและมีHandleProcessCorruptedStateExceptionsAttribute แอตทริบิวต์

สำหรับรายละเอียดเพิ่มเติมโปรดดูที่MSDN


18

ตกลง - ฉันมีมันต่อหน้าฉันบิตของรหัสนี้จากmsdnค่อนข้างอธิบายตัวเองได้:

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
สิ่งนี้ตรงกันข้ามกับคำตอบอื่น ๆ ของ serhio เมื่อเขาพูดว่า: UnhandledExceptionMode.ThrowException ควรตั้งค่าก่อนที่ตัวจัดการเหตุการณ์ ThreadException จะเชื่อมต่อ ไม่แน่ใจว่าคำสั่งนั้นสำคัญจริงๆหรือเปล่า ...
Davide Piras

@DavidePiras ใช่และมีบางอย่างที่มืดมนกว่านี้ SetUnhandledException ดูเหมือนจะไม่สร้างความแตกต่างในกรณีของฉัน
nawfal

0

สิ่งนั้นคือThreadExceptionเกิดขึ้นเนื่องจากปัญหากับเธรดของคุณการทำงานUnhandled Exceptionจะเริ่มทำงานหากรหัสของคุณแสดงข้อยกเว้นที่ไม่ได้รับการจัดการ

วิธีที่ง่ายในการทำให้เกิดข้อที่สองคือการสร้างแอปโดยไม่ต้องพยายาม ... จับบล็อกและโยนข้อยกเว้น

ตอนนี้หากคุณต้องการประกันคุณสามารถจัดการได้ทั้งสองอย่างอย่างไรก็ตามหากคุณจับและจัดการexceptionsได้อย่างถูกต้องคุณก็ไม่จำเป็นต้องใช้UnhandledExceptionตัวจัดการเพราะมันเหมือนกับการจับทั้งหมด


ขอบคุณ - สิ่งที่ฉันไม่ชัดเจนเกินไปคือถ้าจัดการ UnhandledException ฉันจะจับ ThreadException ด้วยซึ่งดูเหมือนจะไม่เป็นเช่นนั้น
JohnIdol
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.