2009-09-03 42 views
61

Đây là phần tiếp theo của tôi initial question và tôi muốn trình bày những phát hiện của mình và yêu cầu chỉnh sửa, ý tưởng và thông tin chi tiết. Phát hiện của tôi (hoặc đúng hơn là giải thích) xuất phát từ câu trả lời của mọi người cho câu hỏi trước của tôi, đọc tài liệu MSDN .NET 3.5 và gỡ lỗi mã .NET 3.5. Tôi hy vọng điều này sẽ có giá trị đối với một người tự hỏi tôi như thế nào để phát hiện khi một ứng dụng chấm dứt.Làm thế nào để phát hiện khi ứng dụng chấm dứt?

Sự kiện:

  • System.AppDomain.CurrentDomain.ProcessExit: tăng khi quá trình thoát, ví dụ sau khi mặc định AppDomain và mọi thứ khác đã được tải xuống [Tổng thời gian thực hiện được giới hạn chỉ trong 3 giây!]. Đối với WPF, thay vào đó hãy sử dụng System.Windows.Application.Exit. Đối với Windows Forms, hãy chạy mã sau Application.Run(...) trong phương thức chính.

  • System.AppDomain.CurrentDomain.DomainUnload: được tăng lên khi số AppDomain khác với mặc định AppDomain unloads, ví dụ: khi chạy các lớp với các khung kiểm thử đơn vị (MbUnit với TestDriven.NET).

  • System.AppDomain.CurrentDomain.UnhandledException: (nếu xử lý theo mặc định AppDomain :) huy động đối với bất kỳ ngoại lệ nào trong bất kỳ chủ đề, không có vấn đề gì AppDomain thread bắt đầu trong Điều này có nghĩa, điều này có thể được sử dụng như là nhận tất cả cho tất cả các trường hợp ngoại lệ unhandled..

  • System.Windows.Application.Exit: được tăng lên khi ứng dụng WPF (ví dụ: mặc định AppDomain) thoát ra một cách duyên dáng. Ghi đè System.Windows.Application.OnExit để tận dụng lợi thế của nó.

  • finalizers (destructors in C#): chạy khi bộ gom rác giải phóng tài nguyên không được quản lý. [Tổng thời gian thực hiện được giới hạn!].

Trình tự các sự kiện:

WPF ứng dụng: thoát duyên dáng

  1. System.Windows.Application.Exit
  2. System.AppDomain.CurrentDomain.ProcessExit
  3. bộ hoàn thiện

WPF ứng dụng: unhandled ngoại lệ

  1. System.AppDomain.CurrentDomain.UnhandledException

MbUnit chạy bên TestDriven.NET: test qua (duyên dáng thoát)

  1. System.AppDomain.CurrentDomain.DomainUnload
  2. bộ hoàn thiện

MbUnit chạy bên trong TestDriven.NET: thất bại trong thử nghiệm (trường hợp ngoại lệ unhandled được xử lý bởi MbUnit)

  1. AppDomain.CurrentDomain.DomainUnload
  2. bộ hoàn thiện

Câu hỏi:

  • Are giải thích của tôi/phát hiện có đúng không?
  • Bạn có biết thêm chi tiết mà tôi có bị bỏ quên không? Ví dụ. tổng số thời gian thực hiện cho finalizers là bao nhiêu?
  • Bạn có biết bất kỳ sự kiện nào khác/ ý tưởng mà tôi biết không?
  • Có sự kiện gì và họ nhận được thứ tự nào trong các ứng dụng khác, ví dụ: Windows Forms, dịch vụ Web, trang web ASP.NET, v.v ...?

Trả lời

7

Được nhắc bởi câu hỏi/trả lời của ssg31415926 (câu hỏi này được đảo ngược một chút), cũng có Application.SessionEnding được gọi khi người dùng đăng xuất hoặc tắt. Nó được gọi trước sự kiện Exit.

+0

Chỉ cần một lưu ý/FYI: đây là chỉ có sẵn trong .NET 3.0+, bạn sẽ cần phải liên kết chống lại System.Core.dll sử dụng nó trong .NET 2.0 –

1
  1. Thời gian chờ mặc định để thực hiện finalizer là 2 giây.
+0

Bạn có một nguồn cho điều đó, phải không? – mbx

+1

@mbx http://msdn.microsoft.com/en-us/library/system.appdomain.processexit.aspx –

2

Khi Dispatcher.BeginInvokeShutdown() được gọi, Application.Exit sẽ không được gọi.

1

Bạn viết:

System.AppDomain.CurrentDomain.UnhandledException:. (Nếu xử lý trong AppDomain mặc định :) huy động đối với bất kỳ ngoại lệ nào trong bất kỳ chủ đề, không có vấn đề gì AppDomain thread bắt đầu trong Điều này có nghĩa, điều này có thể được sử dụng như là tất cả cho tất cả các ngoại lệ chưa được xử lý.

Tôi không nghĩ rằng điều này là chính xác. Hãy thử đoạn mã sau:

using System; 
using System.Threading; 
using System.Threading.Tasks; 

namespace AppDomainTestingUnhandledException 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AppDomain.CurrentDomain.UnhandledException += 
       (sender, eventArgs) => Console.WriteLine("Something went wrong! " + args); 

      var ad = AppDomain.CreateDomain("Test"); 

      var service = 
       (RunInAnotherDomain) 
       ad.CreateInstanceAndUnwrap(
        typeof(RunInAnotherDomain).Assembly.FullName, typeof(RunInAnotherDomain).FullName); 

      try 
      { 
       service.Start(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine("Crash: " + e.Message); 
      } 
      finally 
      { 
       AppDomain.Unload(ad); 
      } 
     } 
    } 

    class RunInAnotherDomain : MarshalByRefObject 
    { 
     public void Start() 
     { 
      Task.Run(
       () => 
        { 
         Thread.Sleep(1000); 
         Console.WriteLine("Uh oh!"); 
         throw new Exception("Oh no!"); 
        }); 

      while (true) 
      { 
       Console.WriteLine("Still running!"); 
       Thread.Sleep(300); 
      } 
     } 
    } 
} 

Theo như tôi có thể nói, xử lý UnhandledException không bao giờ được gọi, và các chủ đề sẽ chỉ lặng lẽ sụp đổ (hoặc nag vào bạn nếu bạn chạy nó trong trình gỡ lỗi).

+0

Tôi thấy rằng dòng đó cũng không rõ ràng. Có lẽ @ user65199 có nghĩa là nếu sự kiện * được "xử lý trong AppDomain mặc định". Rõ ràng, nếu ngoại lệ bị bắt thì sự kiện UnhandledException không được nâng lên. Sự kiện này chỉ được nâng lên trong AppDomain mặc định, ngay cả đối với các ngoại lệ chưa được xử lý đối với các luồng thực sự đã bắt đầu trong một AppDomain khác (trái ngược với ví dụ của bạn bắt đầu từ AppDomain mặc định)? Tôi nghĩ rằng đó có thể là những gì anh ấy nhận được, nhưng tôi không nhớ chắc chắn đó có phải là quy luật hay không. –

0

Chỉ cần thêm một sự kiện mới vào mẫu chính của bạn:

private void frmMain_Load(object sender, EventArgs e) 
{ 
    Application.ApplicationExit += new EventHandler(this.WhenItStopsDoThis); 
} 

private void WhenItStopsDoThis(object sender, EventArgs e) 
{ 
    //Program ended. Do something here. 
} 
Các vấn đề liên quan