У меня необычный случай, когда у меня очень простое исключение, которое бросает и поймает тот же метод. Это не re-thrown (обычный тип проблем у наивных программистов). И все же его StackFrame содержит только один текущий метод. Вот как выглядит:
at (my class).MyMethod() in C:\(my file path and line)
В действительности существует, вероятно, 30 методов, ведущих к этому в стеке вызовов отладчика VS2010, проходя через полдюжины различных сборок. Кажется невозможным, чтобы все это было оптимизировано. Кроме того, этот код построен в режиме отладки без оптимизации, для .NET 4. У меня даже есть (на основе http://msdn.microsoft.com/en-us/library/9dd8z24x.aspx).ini(в том числе один из них [app].vshost.ini) в той же папке, где:
[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0
Кроме того, вызовы методов не находятся в конце методов, поэтому оптимизация хвостовой рекурсии кажется еще маловероятной.
Что касается того, как он называется: нет использования отражения в стеке вызовов, никаких Invoke() или BeginInvoke() любого типа. Это просто длинная цепочка звонков с одного нажатия кнопки. Обработчик кликов составляет около 10 вызовов в стеке вызовов. Под этим вы имеете обычный WndProc, NativeWindow.Callback, встроенные/управляемые переходы и цикл сообщений. Это, в конечном счете, внутри вызова ShowDialog(), который запускается из сборки С# EXE.
Теперь я обнаружил, что могу построить экземпляры класса StackTrace в моем обработчике catch, и если я передаю объект Exception, стек вызовов также будет коротким. Если вместо этого я просто вызываю новый StackTrace() без аргументов, он дает полный стек вызовов.
Ive использовал Reflector, пытаясь отлаживать внутренности класса Exception, который был запущен, и построил его стек вызовов, но я не смог установить точки останова в Exception или в StackTrace. Я мог бы установить их в Environment.GetStackTrace(), и этот метод (который вызывает вызовы) не вызывает вызов во время процесса построения и металирования, но я не знаю, действительно ли отладчик работает правильно. (Этот метод действительно срабатывает для некоторых других вещей, поэтому я не уверен, что с ним делать.)
Вот фрагмент метода:
private void MyMethod()
{
...
try
{
throw new ApplicationException("Test failure");
}
catch (Exception e)
{
StackTrace stackTrace1 = new StackTrace(e);
StackTrace stackTrace2 = new StackTrace(e, false);
StackTrace stackTrace3 = new StackTrace(e, true);
StackTrace stackTrace4 = new StackTrace();
string STs = stackTrace1.ToString() + "\n---\n"
+ stackTrace2.ToString() + "\n---\n"
+ stackTrace3.ToString() + "\n---\n"
+ stackTrace4.ToString();
Log(EventSeverity.Debug, STs);
...
}
}
Это действительно очень просто: исключить Throw, уловить и зарегистрировать его.
Я получаю те же результаты либо в отладчике, либо при автономном выполнении - однострочный стек вызовов. И я знаю, что видел эту проблему в другом месте нашей базы кода. Раньше я предполагал, что это произошло из-за повторных бросков исключений, но во многих случаях он регистрируется прямо в исходном блоке catch. Im довольно сбит с толку, и все веб-поиски, которые я выполнил, ничего не производят.
Это слишком много, чтобы добавить комментарий к предоставленному ответу, но вот еще несколько сведений:
Теперь я вижу, что это поведение обсуждается на http://dotnetthoughts.wordpress.com/2007/10/27/where-did-my-exception-occur/ и что он фактически описан в http://msdn.microsoft.com/en-us/library/system.exception.stacktrace.aspx (хотя я думаю, что можно легко пропустить то, что они там говорят).
Итак, я думаю, что мое "решение" будет немного хитом или пропуском. У нас есть центральный метод, который мы обычно называем форматированием исключений. Внутри этого метода я создам новый StackTrace() как с объектом Exception, так и без него. Затем я буду искать метод, который находится в нижней части трассировки стека Exception, и отобразить все ниже этого в новом StackTrace(), указав, что он был вызван этой серией вызовов.
С другой стороны, конечно, если этот метод не используется, информации там не будет. Но я должен был ожидать какого-то изменения кода где-то.