2012-01-12 28 views
10

Tôi đang điều tra một số sự cố trong ứng dụng của tôi do ngoại lệ Win32 gây ra và tôi đã thu hẹp ngoại lệ rằng nó phải xảy ra trong threadpool đang xử lý trình xử lý sự kiện EventLog.EntryWrittenEventHandler trong ứng dụng. Tôi thiết lập điều này như sau:C# Nắm bắt ngoại lệ xảy ra trên ThreadPool

// Create the event log monitor 
eventLog.Log = "Application"; 
eventLog.EnableRaisingEvents = true; 
eventLog.EntryWritten += new EntryWrittenEventHandler(EventLogMonitor); 

EventLogMonitor là trình xử lý sự kiện của tôi. Tôi tự hỏi không ai có bất kỳ ý tưởng nào về nơi tôi có thể tìm ra cái gì gây ra ngoại lệ này. Có vẻ như để lắng nghe các sự kiện, ThreadPoolWaitOrTimerCallback đang được thiết lập, sẽ không có bất kỳ mã nào của tôi trên đó, và nếu ngoại lệ xảy ra thì tôi không thể xem cách giải quyết vấn đề này. Bất kỳ trợ giúp được thực sự đánh giá cao!!

Dưới đây là sản phẩm của clrstack trong WinDBG:

0:008> !clrstack 
OS Thread Id: 0x106c (8) 
ESP  EIP  
049df1c8 7756f871 [HelperMethodFrame: 049df1c8] 
049df26c 73ce6fa0 System.Diagnostics.EventLog.get_OldestEntryNumber() 
049df27c 73bf24ed System.Diagnostics.EventLog.CompletionCallback(System.Object) 
049df2c4 73bf0fe4 System.Diagnostics.EventLog.StaticCompletionCallback(System.Object, Boolean) 
049df2f4 744fc3b8 System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context(System.Object, Boolean) 
049df300 744fc373 System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context_f(System.Object) 
049df304 7400027f System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 
049df31c 744fc477 System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean) 
049df4ac 74991b5c [GCFrame: 049df4ac] 

Trong trường hợp nó giúp, ứng dụng của tôi chỉ là kiểm tra các sự kiện ID của mỗi entry ghi vào nhật ký sự kiện, và nếu nó phù hợp với một trong một số ID nhất định sau đó tôi đăng nhập nó. Các sự cố xảy ra ít khi xảy ra sự cố và ngoại lệ là ngoại lệ System.ComponentModel.Win32 với thông báo 'Truy cập bị từ chối'. Nghe có vẻ như nó có thể là một vấn đề quyền nhưng tại sao nó sẽ làm việc ok trong một thời gian nhất định và sau đó đột nhiên sụp đổ với điều này.

+0

Những loại trừ nó là gì? –

+0

System.ComponentModel.Win32 ngoại lệ với thông báo 'Truy cập bị từ chối'. Điều kỳ lạ là nó hiếm khi xảy ra, ứng dụng của tôi chạy như một dịch vụ có thể mất vài ngày và đột nhiên nó bị treo với điều này .. – DukeOfMarmalade

+0

Có thể bạn đang cố tạo ra nguồn sự kiện của riêng bạn, chưa bao giờ được sử dụng trước đây, và nó chỉ đổ vỡ sau đó? –

Trả lời

5

Nếu tôi hiểu chính xác (nó sẽ giúp nếu bạn vượt qua stacktrace dẫn bạn đến kết luận rằng ngoại lệ đang xảy ra bên trong một thread threadpool), sau đó chỉ cần quấn mã của EventLogMonitor trong một khối try/catch.

Ví dụ:

void EventLogHandler(object sender, EventArgs args) 
{ 
    try 
    { 
     // Your original code. 
    } 
    catch (Exception ex) 
    { 
     // Log or Write "ex" to the console. Set a breakpoint, whatever. 

     throw; 
    } 
} 

CẬP NHẬT: sau khi cập nhật của bạn có vẻ như nếu ngoại lệ được thực sự không huy động từ bên trong xử lý của bạn, nhưng trước khi nó thậm chí còn được gọi là bên trong lớp EventLog.

Bạn có thể thử đăng ký trình xử lý với sự kiện AppDomain.UnhandledException và thực hiện đăng nhập/xử lý trong đó. Lưu ý rằng điều này sẽ không cho phép bạn ngăn chặn hoặc "thay đổi" hoặc bao gồm ngoại lệ, nhưng chỉ đơn thuần là đăng nhập nó ở đâu đó cho mục đích chẩn đoán.

Nếu bạn chỉ muốn kiểm tra ngoại lệ một lần (hoặc nhân dịp), bạn nên thử sử dụng lệnh !PrintException của tiện ích mở rộng SOS trong WinDBG.

CẬP NHẬT 2: sau khi điều tra thêm, tôi thấy nó khá kỳ lạ khi ngoại lệ bong bóng lên tất cả. Stacktrace của bạn cho thấy bạn đang sử dụng .NET 3.5 (hoặc trước đó, nhưng không phải 4.) và nhìn vào lớp EventLog trong Reflector bạn có thể thấy rằng toàn bộ việc xử lý của EventWrittenHandler, bao gồm cả mã mở đầu có vẻ gây ra ngoại lệ, là bọc trong một khối "try/catch (Exception)/catch" lớn. Buồn cười.

+0

Tôi đã thêm đầu ra của! Clrstack vào câu hỏi của mình. Tôi đã thực sự cố gắng những gì bạn đang đề xuất Christian.K và ứng dụng của tôi vẫn bị hỏng mà không bắn thử/bắt. Ngoại lệ là xảy ra trên một số Threadpool rằng NET phải thiết lập để lắng nghe cho các sự kiện nhập văn bản từ các bản ghi sự kiện, và trường hợp ngoại lệ không propogate trên chủ đề vì vậy tôi không nghĩ rằng điều này sẽ làm việc. Nhờ đề nghị mặc dù! – DukeOfMarmalade

+0

Cảm ơn sự giúp đỡ của bạn về vấn đề này Christian.K, tôi vẫn chưa đến đáy của điều này, đã phải chuyển vấn đề cho Microsoft, gợi ý của bạn đã giúp rất nhiều trong việc điều tra vấn đề này! – DukeOfMarmalade

+0

Quá tệ, chúng tôi không thể tìm ra điều này hoàn toàn. Tôi đã xem xét lại vấn đề, tình cờ, một vài lần, nhưng đã không đưa ra bất kỳ ý tưởng mới (mà không thực sự nói rất nhiều :-). –

0
  1. Nếu có thể, hãy sử dụng Công việc trong System.Threading.Tasks.
  2. Hãy thử, nơi hành động đang thực hiện những gì bạn muốn.

    ThreadPool.QueueUserWorkItem(state => 
    { 
        try 
        { 
         action(); 
        } 
        catch (Exception ex) 
        { 
         OnException(ex); 
        } 
    }); 
    
+0

Tôi không nghĩ rằng điều này sẽ làm việc, khi bạn đăng ký để xử lý sự kiện EventLogEntryWritten một ThreadPool riêng biệt dường như được bắt đầu theo dõi cho các mục ghi vào sổ ghi sự kiện, đó là trên ThreadPool này ngoại lệ xảy ra. – DukeOfMarmalade

1

Theo dõi Application.ThreadException trong Program.cs của bạn như sau để có thể nắm bắt những trường hợp ngoại lệ mà không phải là trong chủ đề chính.

static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.ThreadException += Application_ThreadException; 
     try 
     { 
      Application.Run(new MainForm()); 
     } 
     catch (Exception e) 
     { 
      HandleException(e); 
     } 
    } 

    static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) 
    { 
     HandleException(e.Exception); 
    } 
+2

+1 cho ThreadException! –

0

Không chắc chắn loại ứng dụng này là gì, vì vậy trong trường hợp chung, nếu bạn không gặp may, hãy thử gắn vào AppDomain mà mã đang chạy. Nếu bạn không có nhiều tên miền, bạn có thể thử:

AppDomain.CurrentDomain.FirstChanceException += Handler

hoặc

AppDomain.CurrentDomain.UnhandledException += Handler

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