2016-12-21 1 views
1

Ich habe ein Problem, bei dem, wenn eine Ausnahme innerhalb einer Methode ausgelöst wird, auf die über eine Funktion zugegriffen wird, die Stack-Trace abgeschnitten wird. Betrachten Sie das folgende einfache Reproduktion:Stack-Trace der Exception nicht abgeschlossen, wenn Func geworfen wird

static void Main(string[] args) 
{ 
    Test(); 
    Console.ReadLine(); 
} 

public static void Test() 
{ 
    try 
    { 
     Func<string> func =() => MyFunc(); 
     func(); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine("Exception.StackTrace:"); 
     Console.WriteLine(ex.StackTrace.ToString()); 
    } 
} 

public static string MyFunc() 
{ 
    Console.WriteLine("Environment.StackTrace:"); 
    Console.WriteLine(Environment.StackTrace); 
    Console.WriteLine(new String('*', 20)); 
    throw new Exception("Where is my stack trace?"); 
} 

Ich würde den Stack-Trace erwarten im catch-Block geschrieben grundsätzlich das gleiche wie das in MyFunc geschrieben, sondern in der Tat, was als der Stack-Trace der Ausnahme wird ausgeschrieben ist:

at FuncStackTraceIssue.Program.MyFunc() in Program.cs:line 36 
at FuncStackTraceIssue.Program.<>c.<Test>b__1_0() in Program.cs:line 21 
at FuncStackTraceIssue.Program.Test() in Program.cs:line 22 

wie Sie es nur geht zurück bis in die Funktion, wo ich aufgerufen, um die func (Test) sehen kann. Das Schreiben aus dem Stack-Trace in MyFunc ist:

at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) 
at System.Environment.get_StackTrace() 
at FuncStackTraceIssue.Program.MyFunc() in Program.cs:line 34 
at FuncStackTraceIssue.Program.<>c.<Test>b__1_0() in Program.cs:line 21 
at FuncStackTraceIssue.Program.Test() in Program.cs:line 22 
at FuncStackTraceIssue.Program.Main(String[] args) in Program.cs:line 13 

Der Grund dafür ist mir Probleme verursacht ist, dass in der realen Code ist dies aus mehreren verschiedenen Orten aufgerufen wird und in Variablen und andere solche Dinge geht und wenn es geht schief Ich protokolliere die Ausnahme einschließlich der Stack-Trace. Ich möchte in der Lage sein, genau zu sehen, was der Codepfad ist, der zu dem Fehler führte, und vorzugsweise ohne zu ändern, wie ich logge.

Also die Frage ist, warum bekomme ich nicht einen vollen Stack-Trace und gibt es etwas, was ich tun kann, damit es mir einen vollen Stack-Trace gibt?

+1

Frage mich, ob dies für die Frage gilt, warum nicht vollständige Spur bekommen. Von MSDN: "Die StackTrace-Eigenschaft meldet jedoch möglicherweise nicht so viele Methodenaufrufe wie erwartet, da Codeumwandlungen während der Optimierung auftreten." –

+2

Dies ist von Entwurf. Wenn Sie die Ausnahme abfangen, sagen Sie, dass Sie damit umgehen wollen, und wie Sie damit umgehen, sollte nicht davon abhängen, wer Sie angerufen hat. Wenn dies nicht der Fall ist, fangen Sie es nicht ein. Zu Diagnosezwecken, wenn Sie die Spur von dem, was über dem 'catch' Block ist, wollen, warum verwenden Sie nicht einfach das, was Sie bereits verwenden:' Umgebung.StackTrace' –

+1

Als ein weiterer Kommentar, die gleichen Ergebnisse aus Ihrer einfachen Repro passieren, auch wenn Sie 'Func <>' nicht verwenden, sondern nur die Methode direkt aufrufen. –

Antwort

1

Um zu @Dark Falcon Kommentar oben hinzufügen:

Dies ist nicht unbedingt ein Problem mit Func<>, hat aber mit, wie die StackTrace Eigenschaft Werke zu tun.

Von MSDN's exception class docs (Hervorhebung von mir):

„Im Gegensatz dazu, wenn die Ausnahme erneut ausgelöst durch die Anweisung mit [Beispiel folgt] ... der volle Call-Stack nicht erhalten bleibt, und das Beispiel würde die folgende Ausgabe generieren [Beispiel folgt] ... Eine etwas mühsamere Alternative ist es, eine neue Ausnahme zu werfen, und , um die Call-Stack-Informationen der ursprünglichen Ausnahme in einer internen Ausnahme zu konservieren die neue Ausnahme ist InnerException-Eigenschaft zum Abrufen des Stapelrahmens und anderer Informationen über die ursprüngliche Ausnahme. "

Als mögliche Abhilfe den vollständigen Stack-Trace anmelden, könnten erben Sie von der Exception Klasse und das Hinzufügen von etwas wie ein Stapel Tracer Eigenschaft:

public class StackTraceableException : Exception 
{ 
    readonly string stackTrace; 

    public StackTraceableException() : base() { } 

    public StackTraceableException(string message, string stackTrace) : 
     base(message) 
    { 
     this.stackTrace = stackTrace; 
    } 

    public string StackTrace { get { return stackTrace; } } 
} 

... und mit durch folgen der vorhandene catch Block:

catch (StackTraceableException ex) 
{ 
    Console.WriteLine("Exception.StackTrace:"); 
    Console.WriteLine(ex.StackTrace); 
} 
Verwandte Themen