我发现无法在.NET中的所有线程上转储堆栈.既不发送信号到进程也不编程访问所有线程.我只能通过Thread.CurrentThread访问当前线程.
任何招数?
如果你想在过程已经运行(一拉jstack)得到一个堆栈转储,有作为的两种方法在这里:
有一个鲜为人知但有效的工具叫做Managed Stack Explorer.虽然它具有基本的GUI,但如果你添加到路径,它可以有效地成为jstack的.NET等价物; 然后这只是一个打字的问题:
mse /s /p
下载并安装适用于您的体系结构的适用于Windows版本的调试工具(x86/x64/Itanium)
如果您需要有关Windows函数调用的信息(例如,您想要跟踪内核调用),请下载并安装相应的符号.如果您只想要自己的代码的线程转储,这不是绝对必要的.
如果您需要行号或任何其他详细信息,请确保将程序集的PDB文件放在调试器可以找到它们的位置(通常只是将它们放在实际程序集旁边).
开始 - >程序 - > Windows调试工具[x64] - > windbg
使用菜单将调试器附加到正在运行的进程
为.NET 2.0加载带有".loadby sos mscorwks"的SOS扩展(对于.NET 1.0/1.1,加载".load sos")
使用"!eestack"进行线程转储
使用".detach"分离
我发现有必要采取生产线程转储,这对我有用.希望能帮助到你 :-)
只是为了节省其他人的麻烦,这里的上述端口为c#:
static void WriteThreadInfo(StringBuilder sw, IEnumerablethreads) { 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 = " "; 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(); }
我没有找到一种方法来获取C#中所有托管线程的列表(只有ProcessThreads),所以看起来你需要维护自己感兴趣的线程列表.
另外我发现我无法在正在运行的线程上调用新的Stacktrace(t,true),因此添加了暂停和恢复.显然,你需要考虑这是否会导致问题,如果您要转储生产应用程序.
顺便说一句,我们已将这个调用放在我们的应用程序wcf rest界面上,这样很容易做到.