我正在艰难地追踪锁定问题,因此我想记录每个方法调用的进入和退出。我以前在C++中完成过这样的操作,而无需向每个方法添加代码。在C#中是否可能实现?
我正在艰难地追踪锁定问题,因此我想记录每个方法调用的进入和退出。我以前在C++中完成过这样的操作,而无需向每个方法添加代码。在C#中是否可能实现?
也许您最好的选择是使用AOP(面向切面编程)框架,在方法执行之前和之后自动调用跟踪代码。在AOP和.NET方面,一个受欢迎的选择是PostSharp。
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 ...
*/
}
}
它可能正在等待锁问题的发生,对多个线程进行内存转储和分析调用堆栈。 您可以使用DebugDiag或附带Windows调试工具的adplus脚本(在此情况下为 hang 模式)。
Tess Ferrandez还有一个优秀的实验系列,可以使用.NET内存转储学习调试各种问题。 我强烈推荐它。
你怎么知道这种情况正在发生?如果这是一个多线程应用程序,我建议在运行时测试条件并调用System.Diagnostics.Debugger.Break()来检测它。然后,只需打开线程窗口并逐个步进每个相关线程的调用堆栈。