我在公司的一个较大的应用程序上进行调试,发现了一个并发问题。这个问题只会在运行了很长时间(12个以上小时)后在某些性能较低的机器上出现,并且我从未在调试器中重现过它。因此,我的调试工具基本上仅限于分析日志文件。
C#可以轻松获取抛出异常的线程的堆栈跟踪,但我想额外获取在异常被抛出时正在执行的AppDomain中的每个其他线程的堆栈跟踪。
这种情况是否可能?
我在公司的一个较大的应用程序上进行调试,发现了一个并发问题。这个问题只会在运行了很长时间(12个以上小时)后在某些性能较低的机器上出现,并且我从未在调试器中重现过它。因此,我的调试工具基本上仅限于分析日志文件。
C#可以轻松获取抛出异常的线程的堆栈跟踪,但我想额外获取在异常被抛出时正在执行的AppDomain中的每个其他线程的堆栈跟踪。
这种情况是否可能?
当异常出现时,我建议对进程进行转储。在记录异常的同一位置调用下面的 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.");
}
进入转储目录,您应该会看到一个名为FULLDUMP_something_.dmp的文件夹。
如果您使用.NET4,可以将其拖入VS2010中并检查所有线程或使用并行线程来查看发生了什么(这真是太棒了!)
如果使用NET3.5或更早版本,则需要使用windbg进行分析。请使用以下命令:
~*e !clrstack
来打印所有托管线程的调用堆栈。如果需要更多帮助,请发布回复或在谷歌上搜索教程。