views:

129

answers:

2

If I have a method that I know could potentially recurse infinitely, but I can't reliably predict what conditions/parameters would cause it, what's a good way in C# of doing this:

try
{
  PotentiallyInfiniteRecursiveMethod();
}
catch (StackOverflowException)
{
  // Handle gracefully.
}

Obviously in the main thread you can't do this, but I've been told a few times it's possible to do it using threads or AppDomain's, but I've never seen a working example. Anybody know how this is done reliably?

+11  A: 

You can't. From MSDN

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. Note that an application that hosts the common language runtime (CLR) can specify that the CLR unload the application domain where the stack overflow exception occurs and let the corresponding process continue. For more information, see ICLRPolicyManager Interface and Hosting Overview.

Arcturus
Actually, from that snippet I'd assume that you CAN; it specifically says that a process will continue if the application domain where the exception occurred is unloaded. That implies it's possible to run the method in it's own application domain; my question is, how can this be done?
Flynn1179
This link might prove useful: http://msdn.microsoft.com/en-us/library/dd380850.aspx . It described how to load new application domains. Perhaps that might be the most graceful idea. But hosting a whole new AppDomain seems a bit overkill.. Can you validate the XSLT for circular references?
Arcturus
That's not trivial to do, but that's not the point; I'm looking for a general solution regardless of what's causing the stack overflow.
Flynn1179
For a more general solution, I do think you will need to dive into that domain. I don't think it comes any easier. :(
Arcturus
+1  A: 

There is no way to catch StackOverflowException, but you can do something with unhandled exception:

static void Main()
{
AppDomain.CurrentDomain.UnhandledException += 
  new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}

static void CurrentDomain_UnhandledException
  (object sender, UnhandledExceptionEventArgs e)
{
  try
  {
    Exception ex = (Exception)e.ExceptionObject;

    MessageBox.Show("Whoops! Please contact the developers with the following" 
          + " information:\n\n" + ex.Message + ex.StackTrace, 
          "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
  }
  finally
  {
    Application.Exit();
  }
}
Maciej Czerwiakowski
That won't fire on a StackOverflow exception, I've tried; at least not from within AppDomain.CurrentDomain.
Flynn1179