นี่คือสิ่งที่ฉันค้นพบเมื่อไม่กี่วันที่ผ่านมาฉันได้รับคำยืนยันว่ามันไม่ได้ จำกัด อยู่แค่เครื่องของฉันจากคำถามนี้
วิธีที่ง่ายที่สุดในการทำซ้ำคือเริ่มแอปพลิเคชัน Windows Forms เพิ่มปุ่มและเขียนโค้ดนี้:
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
โปรแกรมล้มเหลวหลังจากคำสั่ง Exit () ดำเนินการ ใน Windows Forms คุณจะได้รับ "ข้อผิดพลาดในการสร้างจุดจับหน้าต่าง"
การเปิดใช้งานการดีบักที่ไม่มีการจัดการทำให้ค่อนข้างชัดเจนว่าเกิดอะไรขึ้น COMห่วงกิริยากำลังดำเนินการและช่วยให้ WM_PAINT ข้อความที่จะส่งมอบ นั่นเป็นอันตรายถึงชีวิตในรูปแบบที่กำจัดทิ้ง
ข้อเท็จจริงเดียวที่ฉันรวบรวมมาคือ:
- ไม่ได้ จำกัด อยู่แค่การรันกับดีบักเกอร์เท่านั้น สิ่งนี้ล้มเหลวหากไม่มี ค่อนข้างต่ำเช่นกัน WER ผิดพลาดแสดงโต้ตอบขึ้นสองครั้ง
- มันไม่ได้มีอะไรเกี่ยวข้องกับบิตของกระบวนการ เลเยอร์ wow64 ค่อนข้างมีชื่อเสียง แต่การสร้าง AnyCPU ขัดข้องในลักษณะเดียวกัน
- ไม่มีส่วนเกี่ยวข้องกับ. NET เวอร์ชัน 4.5 และ 3.5 ขัดข้องในลักษณะเดียวกัน
- รหัสทางออกไม่สำคัญ
- การเรียก Thread.Sleep () ก่อนที่จะเรียก Exit () ไม่สามารถแก้ไขได้
- สิ่งนี้เกิดขึ้นกับ Windows 8 เวอร์ชัน 64 บิตและดูเหมือนว่า Windows 7 จะไม่ได้รับผลกระทบในลักษณะเดียวกัน
- นี่ควรเป็นพฤติกรรมที่ค่อนข้างใหม่ฉันไม่เคยเห็นมาก่อน ฉันไม่เห็นการอัปเดตที่เกี่ยวข้องที่ส่งผ่านWindows Updateแม้ว่าประวัติการอัปเดตจะไม่ถูกต้องในเครื่องของฉันอีกต่อไป
- นี่เป็นการทำลายพฤติกรรมอย่างสิ้นเชิง คุณจะเขียนโค้ดเช่นนี้ในตัวจัดการเหตุการณ์สำหรับ AppDomain.UnhandledException และเกิดปัญหาในลักษณะเดียวกัน
ฉันสนใจเป็นพิเศษว่าคุณสามารถทำอะไรได้บ้างเพื่อหลีกเลี่ยงความผิดพลาดนี้ โดยเฉพาะอย่างยิ่งสถานการณ์ AppDomain.UnhandledException ทำให้ฉันสะดุด ไม่มีหลายวิธีในการยุติโปรแกรม. NET โปรดทราบว่าการเรียก Application.Exit () หรือ Form.Close () ไม่ถูกต้องในตัวจัดการเหตุการณ์สำหรับ UnhandledException ดังนั้นจึงไม่ใช่วิธีแก้ปัญหา
อัปเดต: Mehrdad ชี้ให้เห็นว่าเธรด Finalizer อาจเป็นส่วนหนึ่งของปัญหา ฉันคิดว่าฉันเห็นสิ่งนี้และฉันก็เห็นหลักฐานบางอย่างสำหรับการหมดเวลา 2 วินาทีที่ CLR ให้เธรด Finalizer เพื่อดำเนินการให้เสร็จสิ้น
Finalizer อยู่ภายใน NativeWindowForceExitMessageLoop () มีฟังก์ชัน IsWindow () Win32 ที่ตรงกับตำแหน่งรหัสโดยประมาณโดยชดเชย 0x3c เมื่อดูรหัสเครื่องในโหมด 32 บิต ดูเหมือนว่า IsWindow () จะหยุดชะงัก ฉันไม่สามารถรับการติดตามสแต็กที่ดีสำหรับภายในได้อย่างไรก็ตามดีบักเกอร์คิดว่าการเรียก P / Invokeเพิ่งส่งคืน นี่เป็นเรื่องยากที่จะอธิบาย หากคุณสามารถติดตามสแต็กได้ดีขึ้นฉันก็ชอบที่จะเห็นมัน ของฉัน:
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.ForceExitMessageLoop() + 0x3c bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Finalize() + 0x16 bytes
[Native to Managed Transition]
kernel32.dll!@BaseThreadInitThunk@12() + 0xe bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
ไม่มีสิ่งใดเหนือการเรียก ForceExitMessageLoop เปิดใช้งานดีบักเกอร์ที่ไม่มีการจัดการ