我如何添加Trace()到C#中的每个方法调用?
我很难跟踪locking问题,所以我想logging每个方法调用的进入和退出。 我以前用C ++做过,而不必为每个方法添加代码。 这可能与C#?
也许你最好的select是使用AOP(面向方面编程)框架在方法执行之前和之后自动调用跟踪代码。 AOP和.NET的stream行select是PostSharp 。
分析器非常适合在开发过程中查看正在运行的代码,但是如果您正在寻找能够在生产环境中执行自定义跟踪的function,那么,正如Denis G.所说, PostSharp是一个完美的工具:您不必更改你的代码,你可以轻松地打开/closures它。
在几分钟内设置也很容易,而且PostSharp的创build者GaëlFraiteur甚至有video,显示了向现有应用程序添加跟踪是多么容易。
您将在文档部分find示例和教程。
如果你的主要目标是logging函数的入口/出口点和偶尔的信息,我用一个Disposablelogging对象获得了很好的结果,其中构造函数跟踪函数入口 ,而Dispose()跟踪出口 。 这允许调用代码简单地将每个方法的代码包装在一个using语句中。 还提供了方法之间的任意日志。 下面是一个完整的C#ETW事件跟踪类以及一个函数入口/出口包装:
using System; using System.Diagnostics; using System.Diagnostics.Tracing; using System.Reflection; using System.Runtime.CompilerServices; namespace MyExample { // This class traces function entry/exit // Constructor is used to automatically log function entry. // Dispose is used to automatically log function exit. // use "using(FnTraceWrap x = new FnTraceWrap()){ function code }" pattern for function entry/exit tracing public class FnTraceWrap : IDisposable { string methodName; string className; private bool _disposed = false; public FnTraceWrap() { StackFrame frame; MethodBase method; frame = new StackFrame(1); method = frame.GetMethod(); this.methodName = method.Name; this.className = method.DeclaringType.Name; MyEventSourceClass.Log.TraceEnter(this.className, this.methodName); } public void TraceMessage(string format, params object[] args) { string message = String.Format(format, args); MyEventSourceClass.Log.TraceMessage(message); } public void Dispose() { if (!this._disposed) { this._disposed = true; MyEventSourceClass.Log.TraceExit(this.className, this.methodName); } } } [EventSource(Name = "MyEventSource")] sealed class MyEventSourceClass : EventSource { // Global singleton instance public static MyEventSourceClass Log = new MyEventSourceClass(); private MyEventSourceClass() { } [Event(1, Opcode = EventOpcode.Info, Level = EventLevel.Informational)] public void TraceMessage(string message) { WriteEvent(1, message); } [Event(2, Message = "{0}({1}) - {2}: {3}", Opcode = EventOpcode.Info, Level = EventLevel.Informational)] public void TraceCodeLine([CallerFilePath] string filePath = "", [CallerLineNumber] int line = 0, [CallerMemberName] string memberName = "", string message = "") { WriteEvent(2, filePath, line, memberName, message); } // Function-level entry and exit tracing [Event(3, Message = "Entering {0}.{1}", Opcode = EventOpcode.Start, Level = EventLevel.Informational)] public void TraceEnter(string className, string methodName) { WriteEvent(3, className, methodName); } [Event(4, Message = "Exiting {0}.{1}", Opcode = EventOpcode.Stop, Level = EventLevel.Informational)] public void TraceExit(string className, string methodName) { WriteEvent(4, className, methodName); } } }
使用它的代码将如下所示:
public void DoWork(string foo) { using (FnTraceWrap fnTrace = new FnTraceWrap()) { fnTrace.TraceMessage("Doing work on {0}.", foo); /* code ... */ } }
从红门使用ant探查器将是你最好的select。 如果没有,在温莎城堡看看拦截器 。 这确实假设你正在通过IoC加载你的types。
reflection是另一种方式,您可以使用System.Reflection.Emit方法将代码“写入”内存。 该代码可以replace你的方法的代码,并执行它,但适当的日志logging。 祝你好运,虽然…更容易使用面向方面的编程框架,如方面# 。
它可能正在等待locking问题,进行内存转储并分析各个线程上的调用堆栈。 您可以使用debugging工具for Windows附带的DebugDiag或adplus脚本(在本例中为挂起模式)。
Tess Ferrandez也有一个很好的实验系列 ,学习使用.NET内存转储来debugging各种问题。 我强烈推荐它。
你怎么知道这是发生? 如果这是一个multithreading应用程序,我会build议testing条件,并在运行时检测到时调用System.Diagnostics.Debugger.Break()。 然后,只需打开“线程”窗口,然后遍历每个相关线程的调用堆栈。
尝试jetbrains dottrace它是一个.NET性能分析器。 你不必修改你的代码。 它给你10天的审判。
这里是一个dottrace教程