1

I have a windows service with the following code

AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

private static void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
    {
          if (e.Exception == null)
            return;

          LogException(e.Exception, "FirstChance Exception ");
    }

    public void Test()
    {
      Task.Factory.StartNew(x =>
            {
               foreach(item in blockingCollection.GetConsumingEnumerable())
               {
                  try
                  {
                     Convert.ToInt32("Test");
                  }
                  catch (Exception ex)
                  {
                  }
               }
            });            
        }

Inside Test method catch I can see full stack trace

 at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Convert.ToInt32(String value)
   at Test.TestService.<QueueConsumer>b__11_0(Object x) in C:\SourceControl\TestProject.Risk\Application\TestService.cs:line 157

whereas in private static void CurrentDomain_FirstChanceException I see incomplete stacktrace

System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)

If I remove try{}catch{} CurrentDomain_UnhandledException event is not fired

I want to avoid try{}catch{} just to log the exception. How can I get the complete stacktrace in the first chance exception?

codejunkie
  • 83
  • 9
  • 1
    You can't. The missing info is added to the exception after the return from CurrentDomain_FirstChanceException() method – jdweng Oct 26 '17 at 10:20
  • 1
    You can't, because that *is* the full stack trace (or rather, just the method info packaged as a stack trace). "First chance" means the handler is invoked before the stack is unwound to find an exception handler (if any). Short of attaching a debugger and have it handle the first chance notification by doing a stack walk (which I'm pretty sure you cannot do from inside your own process) I don't think this is possible. Consider using the `catch (Exception ex) { log(ex); throw; }` pattern instead. This should be used sparingly, since handled exceptions are not normally something you log. – Jeroen Mostert Oct 26 '17 at 10:21
  • That makes sense. but even if I remove try catch the service does not crash. I have edited ```Test()``` and added the TPL code. – codejunkie Oct 26 '17 at 11:17
  • That's because you're [not observing the results of the task](https://docs.microsoft.com/dotnet/standard/parallel-programming/exception-handling-task-parallel-library). If you need your service to hard crash on an unhandled exception, register a `.ContinueWith(OnlyOnFaulted)` continuation that explicitly creates a new thread that throws the exception. You can also use [`ThrowUnobservedTaskExceptions`](https://docs.microsoft.com/dotnet/api/system.threading.tasks.taskscheduler.unobservedtaskexception), but this only triggers when the task is garbage-collected. Or, of course, just get the result. – Jeroen Mostert Oct 26 '17 at 11:23
  • I have dozens of tasks. This would be inefficient to add continueWith on all places. Is there anything similar to ```AppDomain.CurrentDomain.UnhandledException```? – codejunkie Oct 26 '17 at 11:25
  • You mean like `TaskScheduler.UnobservedTaskException`, which I just linked to? :-) Note that even with "dozens of tasks", if *all* of them aren't handling exceptions, you're Doing It Wrong. Typically you would only have one outer task where it's important the exceptions are handled synchronously. Inside the tasks, exceptions should be caught and handled as normal. Also, the `.ContinueWith` logic is easily wrapped in an extension method. If your code is silently faulting all over the place, that's a good thing to fix before worrying about "efficiency". – Jeroen Mostert Oct 26 '17 at 11:27
  • Yes just saw it. Thanks. Exception is logged on TaskScheduler.UnobservedTaskException but service still is up and running – codejunkie Oct 26 '17 at 11:30
  • `Environment.FailFast` or `new Thread(() => { throw ex; }).Start()` would fix that. – Jeroen Mostert Oct 26 '17 at 11:31
  • @JeroenMostert where should I add this? And again the stacktrace is incomplete in TaskScheduler.UnobservedTaskException – codejunkie Oct 26 '17 at 11:32
  • At the point you have the exception and want your service to crash; that is, after logging it in the unobserved exception handler. For the most complete logging, you need an unhandled exception to occur on a thread. That means actually observing the results of all your tasks. I've never used `.UnobservedTaskException` myself; it would only be good as a detection mechanism to see where your exception handling is incomplete. – Jeroen Mostert Oct 26 '17 at 11:33
  • Environment.FailFast or new Thread(() => { throw ex; }).Start() didnt make the trick. Can you write it as answer so I can mark it as answer? – codejunkie Oct 26 '17 at 11:39

0 Answers0