我发现无法在.NET中的所有线程上转储堆栈.既不发送信号到进程也不编程访问所有线程.我只能通过Thread.CurrentThread访问当前线程.
任何招数?
Tom*_*bel 11
如果你想在过程已经运行(一拉jstack)得到一个堆栈转储,有作为的两种方法在这里:
有一个鲜为人知但有效的工具叫做Managed Stack Explorer.虽然它具有基本的GUI,但如果你添加到路径,它可以有效地成为jstack的.NET等价物; 然后这只是一个打字的问题:
mse /s /p <pid>
我发现有必要采取生产线程转储,这对我有用.希望能帮助到你 :-)
只是为了节省其他人的麻烦,这里的上述端口为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界面上,这样很容易做到.
System.Diagnostics 中有各种方便的类可以帮助您调试和收集各种跟踪信息,例如 StackTrace。
有一个奇怪的 Process 类可用于获取执行线程的数量,但细节很少。使用以下代码片段:
Using System.Diagnostics;
var threads = Process.GetCurrentProcess().Threads;
Run Code Online (Sandbox Code Playgroud)
好吧,在仔细查看之后,发现捕获所有当前堆栈的最简单方法是通过小型转储和SOS之类的工具,或者如果您运行的是 vista,则可以使用此工具。
祝你好运。