Dre*_*fer 22 c# debugging concurrency multithreading stack-trace
我正在调试一个明显的并发问题,这是一个我在工作中遇到的大应用程序.有问题的错误仅在运行了许多(12+)小时后出现在某些性能较低的机器上,我从未在调试器中重现它.因此,我的调试工具基本上只限于分析日志文件.
C#可以很容易地获得抛出异常的线程的堆栈跟踪,但是我还想在抛出异常时另外获取当前在我的AppDomain中执行的每个其他线程的堆栈跟踪.
这可能吗?
CodePlex上有一个名为Managed Stack Explorer的工具(我认为它来自Microsoft).它使用调试和分析API来捕获正在运行的.Net应用程序中的线程的堆栈跟踪,而无需修改应用程序.
您可以在遇到问题之前运行应用程序,然后使用此工具对其进行分析,以捕获所有正在运行的线程的当前堆栈跟踪.这种方法的好处是您可以不修改应用程序(检测它可能会改变其行为),并且该工具是免费的.
我建议在异常发生时转储进程.在您记录异常的同一个地方,调用MakeDumpFile()方法,如下所示.
假设您在有问题的计算机上安装了Windows调试工具.
private static void MakeDumpFile()
{
int pid = Process.GetCurrentProcess().Id;
Console.WriteLine("Creating dump for pid " + pid);
//path to adplus executable; ensure you have Debugging tools installed;
string program = @"C:\Program Files (x86)\Debugging Tools for Windows (x86)\adplus.exe";
//args for adplus; ensure the crashdump folder exists!
string args = string.Format(@"-hang -p {0} -o c:\crashdump", pid);
var startInfo = new ProcessStartInfo(program, args);
startInfo.UseShellExecute = false;
startInfo.ErrorDialog = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = true;
var process = Process.Start(startInfo);
Console.WriteLine("The following is output from adplus");
Console.WriteLine(process.StandardOutput.ReadToEnd());
Console.WriteLine("Finished creating dump.");
}
Run Code Online (Sandbox Code Playgroud)
导航到转储目录,您应该看到一个新文件夹,其中包含一个名为FULLDUMP_something_.dmp的文件.
如果您使用的是.NET4,只需将其拖入VS2010并检查所有线程或使用并行线程查看发生了什么(这太棒了!)
如果在NET3.5或更早版本,您将需要使用windbg进行分析.使用以下命令
〜*e!clrstack
打印所有托管线程的callstack.如果您需要更多帮助,请将windbg发回或谷歌获取教程.