如何在.NET中进行线程转储?(一个JVM线程转储)

24 .net c#

我发现无法在.NET中的所有线程上转储堆栈.既不发送信号到进程也不编程访问所有线程.我只能通过Thread.CurrentThread访问当前线程.

任何招数?

Tom*_*bel 11

如果你想在过程已经运行(一拉jstack)得到一个堆栈转储,有作为的两种方法在这里:

使用托管堆栈资源管理器

有一个鲜为人知但有效的工具叫做Managed Stack Explorer.虽然它具有基本的GUI,但如果你添加到路径,它可以有效地成为jstack的.NET等价物; 然后这只是一个打字的问题:

mse /s /p <pid>

使用windbg

  1. 下载并安装适用于您的体系结构的适用于Windows版本的调试工具(x86/x64/Itanium)
  2. 如果您需要有关Windows函数调用的信息(例如,您想要跟踪内核调用),请下载并安装相应的符号.如果您只想要自己的代码的线程转储,这不是绝对必要的.
  3. 如果您需要行号或任何其他详细信息,请确保将程序集的PDB文件放在调试器可以找到它们的位置(通常只是将它们放在实际程序集旁边).
  4. 开始 - >程序 - > Windows调试工具[x64] - > windbg
  5. 使用菜单将调试器附加到正在运行的进程
  6. 为.NET 2.0加载带有".loadby sos mscorwks"的SOS扩展(对于.NET 1.0/1.1,加载".load sos")
  7. 使用"!eestack"进行线程转储
  8. 使用".detach"分离

我发现有必要采取生产线程转储,这对我有用.希望能帮助到你 :-)

  • 注意mse目前只是用.Net 2.0编写的应用程序的一个选项,因为它用于收集数据的诊断API已在.Net 4.0中弃用. (7认同)
  • MSE链接显示"我们很抱歉,此下载不再可用." (3认同)

Squ*_*rel 6

只是为了节省其他人的麻烦,这里的上述端口为c#:

    static void WriteThreadInfo(StringBuilder sw, IEnumerable<Thread> threads)
    {
        foreach(Thread thread in threads)
        {
            if(!thread.IsAlive) continue;
            sw.Append(String.Concat("THREAD NAME: ", thread.Name));

            sw.Append(GetStackTrace(thread));
            sw.AppendLine();
            sw.AppendLine();
        }
    }

    static String GetStackTrace(Thread t)
    {
        t.Suspend();
        var trace1 = new StackTrace(t, true);
        t.Resume();

        String  text1 = System.Environment.NewLine;
        var builder1 = new StringBuilder(255);
        for (Int32 num1 = 0; (num1 < trace1.FrameCount); num1++)
        {
            StackFrame  frame1 = trace1.GetFrame(num1);
            builder1.Append("   at ");
            System.Reflection.MethodBase  base1 = frame1.GetMethod();
            Type  type1 = base1.DeclaringType;
            if (type1 != null)
            {
                String  text2 = type1.Namespace;
                if (text2 != null)
                {
                    builder1.Append(text2);
                    builder1.Append(".");                                                
                }
                builder1.Append(type1.Name);
                builder1.Append(".");
            }
            builder1.Append(base1.Name);
            builder1.Append("(");
            System.Reflection.ParameterInfo [] infoArray1 = base1.GetParameters();
            for (Int32 num2 = 0; (num2 < infoArray1.Length); num2++)
            {
                String text3 = "<UnknownType>";
                if (infoArray1[num2].ParameterType != null)
                {
                                text3 = infoArray1[num2].ParameterType.Name;
                }
                builder1.Append(String.Concat(((num2 != 0) ? ", " : ""), text3, " ", infoArray1[num2].Name));
            }
            builder1.Append(")");
            if (frame1.GetILOffset() != -1)
            {
                String text4 = null;
                try
                {
                    text4 = frame1.GetFileName();
                }
                catch (System.Security.SecurityException)
                {
                }
                if (text4 != null)
                {
                    builder1.Append(String.Concat(" in ", text4, ":line ", frame1.GetFileLineNumber().ToString()));
                }
            }
            if (num1 != (trace1.FrameCount - 1))
            {
                builder1.Append(text1);
            }
        }
        return builder1.ToString();
    }
Run Code Online (Sandbox Code Playgroud)

我没有找到一种方法来获取C#中所有托管线程的列表(只有ProcessThreads),所以看起来你需要维护自己感兴趣的线程列表.

另外我发现我无法在正在运行的线程上调用新的Stacktrace(t,true),因此添加了暂停和恢复.显然,你需要考虑这是否会导致问题,如果您要转储生产应用程序.

顺便说一句,我们已将这个调用放在我们的应用程序wcf rest界面上,这样很容易做到.


sma*_*ell 0

System.Diagnostics 中有各种方便的类可以帮助您调试和收集各种跟踪信息,例如 StackTrace。

有一个奇怪的 Process 类可用于获取执行线程的数量,但细节很少。使用以下代码片段:

Using  System.Diagnostics;

var threads = Process.GetCurrentProcess().Threads;
Run Code Online (Sandbox Code Playgroud)

好吧,在仔细查看之后,发现捕获所有当前堆栈的最简单方法是通过小型转储和SOS之类的工具,或者如果您运行的是 vista,则可以使用此工具。

祝你好运。

  • 是的,这个答案的第一部分不起作用,因为 Process.GetCurrentProcess().Threads 为您获取与托管线程没有 1:1 对应关系的操作系统线程,因此您无法从 ProcessThread 到 System.Thread为了获取堆栈跟踪。 (4认同)