我可以在c#app中获取所有线程的堆栈跟踪吗?

Dre*_*fer 22 c# debugging concurrency multithreading stack-trace

我正在调试一个明显的并发问题,这是一个我在工作中遇到的大应用程序.有问题的错误仅在运行了许多(12+)小时后出现在某些性能较低的机器上,我从未在调试器中重现它.因此,我的调试工具基本上只限于分析日志文件.

C#可以很容易地获得抛出异常的线程的堆栈跟踪,但是我还想在抛出异常时另外获取当前在我的AppDomain中执行的每个其他线程的堆栈跟踪.

这可能吗?

adr*_*nks 6

CodePlex上有一个名为Managed Stack Explorer的工具(我认为它来自Microsoft).它使用调试和分析API来捕获正在运行的.Net应用程序中的线程的堆栈跟踪,而无需修改应用程序.

您可以在遇到问题之前运行应用程序,然后使用此工具对其进行分析,以捕获所有正在运行的线程的当前堆栈跟踪.这种方法的好处是您可以不修改应用程序(检测它可能会改变其行为),并且该工具是免费的.

  • 不要再认为这在.NET4中是受支持的,即使示例应用程序没有显示在安装了.NET4的PC上的列表中. (4认同)

wal*_*wal 5

我建议在异常发生时转储进程.在您记录异常的同一个地方,调用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发回或谷歌获取教程.