2012-05-22 41 views
11

Tôi đang sử dụng sự kiện FirstChanceException để ghi lại chi tiết về bất kỳ trường hợp ngoại lệ nào bị ném.AppDomain.FirstChanceException và ngoại lệ tràn ngăn xếp

static void Main(string[] args) 
{ 
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => 
    { 
     Console.WriteLine("Inside first chance exception."); 
    }; 

    throw new Exception("Exception thrown in main."); 
} 

Điều này hoạt động như mong đợi. Nhưng nếu một ngoại lệ được ném bên trong xử lý sự kiện, một tràn ngăn xếp sẽ xảy ra kể từ khi sự kiện sẽ được nâng lên đệ quy.

static void Main(string[] args) 
{ 
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => 
    { 
     throw new Exception("Stackoverflow"); 
    }; 

    throw new Exception("Exception thrown in main."); 
} 

Làm cách nào để xử lý các ngoại lệ xảy ra trong trình xử lý sự kiện?

Edit:

Có một vài câu trả lời gợi ý rằng tôi quấn mã bên trong xử lý sự kiện trong một khối try/catch, nhưng điều này không làm việc kể từ khi sự kiện này được nâng lên trước khi ngoại lệ có thể được xử lý.

static void Main(string[] args) 
{ 
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => 
    { 
     try 
     { 
      throw new Exception("Stackoverflow"); 
     } 
     catch 
     { 
     } 
    }; 

    throw new Exception("Exception thrown in main."); 
} 
+0

Chỉ cần sử dụng một lĩnh vực bool để ngăn chặn đệ quy. –

+0

Tôi không hiểu tại sao bạn lại muốn điều này. Ngoại lệ cơ hội đầu tiên được xử lý. Tại sao bạn lại ném một cái khác? – leppie

+0

Tôi không cố ý ném một số khác. Điều gì xảy ra nếu tôi đang cố gắng để đăng nhập lỗi đó và một ngoại lệ được ném trong khi tôi đang cố gắng để đăng nhập thông tin đó? – nivlam

Trả lời

-1

Trong ngoại lệ chung, bạn có thể xử lý giống như tất cả những người khác, nhưng những gì về nói riêng StackOverflowOutOfMemory ngoại lệ, họ không thể được xử lý trong .NET Framework.

Look đây: How do I prevent and/or handle a StackOverflowException? (C#)

Bắt đầu với phiên bản .NET Framework 2.0, một StackOverflowException đối tượng không thể được đánh bắt bởi một khối try-catch và quá trình tương ứng được chấm dứt theo mặc định. Do đó, người dùng được khuyên nên viết mã của họ để phát hiện và ngăn chặn tràn ngăn xếp. Ví dụ: nếu đơn đăng ký của bạn tùy thuộc vào đệ quy, hãy sử dụng bộ đếm hoặc trạng thái để chấm dứt vòng lặp đệ quy.

+0

Tôi không tìm cách bắt một ngoại lệ stackoverflow. Tôi đang tìm cách ngăn chặn nó xảy ra. – nivlam

+0

@nivlam: để ngăn chặn nó xảy ra chỉ cần không gọi chức năng tạo ra tràn ngăn xếp trong một cách * * bạn gọi nó. Bạn đang tìm kiếm giải pháp gì, vì vậy ?? – Tigran

-1

Tôi nghĩ thêm một try {} catch(){} khối trong xử lý ngoại lệ sẽ giúp

static void Main(string[] args) 
{ 
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => 
    { 
     try { 
      throw new Exception("Stackoverflow"); 
     } catch (Exception e) 
     { 
      // Do something very simple not throwing an exception... 
     } 
    }; 

    throw new Exception("Exception thrown in main."); 
} 
+1

Điều này không hoạt động. Sự kiện FirstChanceException được nâng lên trước khi ngoại lệ có thể được xử lý trong khối catch. – nivlam

-1

Xử lý trong trường hợp ngoại lệ bằng tay ví dụ

static void Main(string[] args) { 
    AppDomain.CurrentDomain.FirstChanceException += (sender, eventArgs) => 
    { 
     try{ 
     throw new Exception("Stackoverflow");} catch (Exception ex){/*manual handle*/} 
    }; 
     throw new Exception("Exception thrown in main."); 
} 
0

Bài viết MSDN bạn liên kết làm cho một vài recommandations:

Bạn phải xử lý tất cả trường hợp ngoại lệ xảy ra trong xử lý sự kiện cho sự kiện FirstChanceException. Nếu không, FirstChanceException được nâng lên đệ quy. Điều này có thể dẫn đến tràn ngăn xếp và chấm dứt ứng dụng. Chúng tôi khuyên bạn nên triển khai trình xử lý sự kiện cho sự kiện này dưới dạng các vùng thực thi hạn chế (CER), để giữ các ngoại lệ liên quan đến cơ sở hạ tầng như bộ nhớ ngoài hoặc ngăn xếp ngăn ảnh hưởng đến máy ảo trong khi thông báo ngoại lệ đang được xử lý.

Vì vậy, kèm theo chức năng của bạn bên trong một khối try/catch, và gọi PrepareConstrainedRegion trước khối để tránh trường hợp ngoại lệ OutOfMemory: http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions.aspx

Edit: Vâng, bạn vẫn còn có vấn đề đệ quy ngay cả với try/bắt khối. Vì vậy ... tôi đoán bạn chỉ cần gọi mã an toàn mà không ném bất kỳ ngoại lệ nào. Trình xử lý sự kiện đó có vẻ khá nguy hiểm, tôi khuyên bạn nên sử dụng nó chỉ cho mục đích gỡ lỗi.

+0

Bất kỳ vấn đề nào về hiệu năng trong ASP.NET? Tôi có một ** sản xuất dump ** cho ứng dụng của tôi _ASP.NET 4.6.1_. Có _7000 ngoại lệ_ (*** ngoại lệ cơ hội đầu tiên ***) chỉ trong 20 phút. Tôi cần log _first cơ hội exceptions_ một cách an toàn cho nghiên cứu vấn đề, mà không nhận được *** stackoverflow hoặc outofmemory ngoại lệ *** – Kiquenet

0

đầu tiên sử dụng một phương pháp thay vì một đại biểu, vì vậy tên phương pháp sẽ được xác định

Sau đó sử dụng Environment.StackTrace để kiểm tra xem phương pháp này là đã có trong stacktrace

Dưới đây là một đoạn mã chưa được kiểm tra:

static void Main(string[] args) 
{ 
    AppDomain.CurrentDomain.FirstChanceException += handleFirstChanceException; 
} 

private void handleFirstChanceException(object sender, EventArgs eventArgs) 
{ 
    if (Environment.StackTrace.Contains("handleFirstChanceException")) 
     return; 

    // handle 
} 

tôi nghĩ rằng ở trên sẽ không làm việc vì nó sẽ luôn chứa tên phương pháp, nhưng bạn có thể tin tưởng nếu nó xuất hiện nhiều hơn 1 lần. Ngoài ra, hãy kiểm tra xem nó không được gạch chân khi bạn biên dịch trong Chế độ phát hành, trong trường hợp này bạn đang gặp sự cố

+0

Điều gì sẽ xảy ra khi tài sản 'Environment.StackTrace' getter ném một ngoại lệ? – hvd

+0

Tại sao nó nên ném? Doc (http://msdn.microsoft.com/en-us/library/system.environment.stacktrace.aspx) nói rằng nó chỉ có thể ném một ArgumentOutOfRangeException nhưng tôi không thể trong trường hợp – Fabske

+0

Bất cứ điều gì luôn có thể ném một 'OutOfMemoryException' . Điều này sẽ kích hoạt ngoại lệ cơ hội đầu tiên và cố gắng lấy một dấu vết ngăn xếp khác, cũng sẽ không thành công, vì bạn đã hết bộ nhớ. – hvd

1

Mặc dù đây không phải là cách tốt, trong VB .NET bạn có thể ngăn chặn việc loại trừ ngoại lệ trong trình xử lý sự kiện FirstChanceException bằng cách sử dụng " Trên báo cáo lỗi tiếp tục lại "tuyên bố, đến từ VB 6. (Tôi không chắc chắn nếu C# có một cái gì đó tương tự) Ngoài ra, bạn nên ngăn chặn đệ quy trên xử lý sự kiện như đã đề cập here. Sau đây là mã mẫu, dường như hoạt động như mong đợi.

Sub Main(args As String()) 
    AddHandler AppDomain.CurrentDomain.FirstChanceException, AddressOf FirstChanceExceptionEventHandler 
    Throw New Exception("Exception thrown in main.") 
End Sub 

Private Sub FirstChanceExceptionEventHandler(ByVal source As Object, ByVal e As FirstChanceExceptionEventArgs) 
    On Error Resume Next 

    Dim frames As StackFrame() = New StackTrace(1).GetFrames() 
    Dim currentMethod As MethodBase = MethodBase.GetCurrentMethod() 
    If frames IsNot Nothing AndAlso frames.Any(Function(x) x.GetMethod() = currentMethod) Then 
     Return 
    Else 
     Throw New Exception("Stackoverflow") 
    End If 
End Sub 
4

này đang làm việc cho tôi:

private volatile bool _insideFirstChanceExceptionHandler;  

// ... 

AppDomain.CurrentDomain.FirstChanceException += OnFirstChanceException; 

// ... 

private void OnFirstChanceException(object sender, FirstChanceExceptionEventArgs args) 
{ 
    if (_insideFirstChanceExceptionHandler) 
    { 
     // Prevent recursion if an exception is thrown inside this method 
     return; 
    } 

    _insideFirstChanceExceptionHandler = true; 
    try 
    { 
     // Code which may throw an exception 
    } 
    catch 
    { 
     // You have to catch all exceptions inside this method 
    } 
    finally 
    { 
     _insideFirstChanceExceptionHandler = false; 
    } 
} 
+0

Điều này thực sự là đúng cách để làm điều này, nó phải được đánh dấu câu trả lời được chấp nhận. Bạn có thể phải tăng thêm mã để quản lý các appdomain khác nhau, nhưng nếu không, giải pháp tốt đẹp! – Abel

+0

giải pháp tốt đẹp, bạn đã lưu ngày của tôi –

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