I\'m using the FirstChanceException event to log details about any thrown exceptions.
static void Main(string[] args)
{
AppDomain.CurrentDomain.FirstChanceEx
First use a method instead of a delegate, so the method name will be defined
Then use Environment.StackTrace to check if the method is already in the stacktrace
Here is a piece of code untested:
static void Main(string[] args)
{
AppDomain.CurrentDomain.FirstChanceException += handleFirstChanceException;
}
private void handleFirstChanceException(object sender, EventArgs eventArgs)
{
if (Environment.StackTrace.Contains("handleFirstChanceException"))
return;
// handle
}
I think the above will not work because it'll always contains the method name, but you can count if it appear more than 1 time. Also, check that it's not inlined when you compile in Release mode, in this case you're in trouble
The MSDN article you linked makes a few recommandations:
You must handle all exceptions that occur in the event handler for the FirstChanceException event. Otherwise, FirstChanceException is raised recursively. This could result in a stack overflow and termination of the application. We recommend that you implement event handlers for this event as constrained execution regions (CERs), to keep infrastructure-related exceptions such as out-of-memory or stack overflow from affecting the virtual machine while the exception notification is being processed.
So enclose your function inside a try/catch block, and call PrepareConstrainedRegion
before the block to avoid OutOfMemory exceptions: http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions.aspx
Edit: Well, you still have the recursion issue even with the try/catch block. So... I guess you just have to call only safe code that won't throw any exception. That event handler seems quite dangerous, I'd recommend to use it only for debugging purpose.
I think adding another try {} catch (){}
block in the exception handler would help
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.");
}
This is working for me:
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;
}
}
Eventhough it is not a good way, in VB .NET you can prevent exception firing inside FirstChanceException event handler using "On Error Resume Next" statement, coming from VB 6. (I am not sure if C# has something similar) Additionally, you should prevent recursion on the event handler as mentioned here. Following is the sample code, seems to work as expected.
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
In general exception you can handle like all others, but what about in particular StackOverflow
and OutOfMemory
exception, they can not be handled in .NET Framework.
Look here: How do I prevent and/or handle a StackOverflowException? (C#)
Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default. Consequently, users are advised to write their code to detect and prevent a stack overflow. For example, if your application depends on recursion, use a counter or a state condition to terminate the recursive loop.