在java中,可以获取所有正在运行的线程的堆栈跟踪的快照。
这是通过java.lang.Thread.getAllStackTraces()
完成的(它返回Map<Thread,StackTraceElement[]>
)。
如何用.net?
完成答案 0 :(得分:23)
所以我实际上只是想弄清楚如何做到这一点 - 还没有在生产中广泛使用这个解决方案,但是还有一个名为ClrMd的相对较新的库。
使用它,我能够附加到我自己的进程并获得所有活动线程的堆栈跟踪。在重新启动我们的应用程序之前检测到死锁时使用此方法,如下所示:
var result = new Dictionary<int, string[]>();
var pid = Process.GetCurrentProcess().Id;
using (var dataTarget = DataTarget.AttachToProcess(pid, 5000, AttachFlag.Passive))
{
ClrInfo runtimeInfo = dataTarget.ClrVersions[0];
var runtime = runtimeInfo.CreateRuntime();
foreach (var t in runtime.Threads)
{
result.Add(
t.ManagedThreadId,
t.StackTrace.Select(f =>
{
if (f.Method != null)
{
return f.Method.Type.Name + "." + f.Method.Name;
}
return null;
}).ToArray()
);
}
}
var json = JsonConvert.SerializeObject(result);
zip.AddEntry("_threads.json", json);
从同一个流程开始工作非常重要的是AttachFlag.Passive
如果你只是做DataTarget.AttachToProcess(pid, 5000)
,它会做一个&#34;入侵&#34;附加试图暂停该过程。当您尝试附加到自己的流程时,这会引发异常,我假设是因为您在尝试从应用程序或类似内容中附加时暂停应用程序。
无论如何,是的,很酷的东西。
如果任何人有任何理由为什么这是超级天真或任何事情,pleeeeease指出他们。 Haven还没有在生产中使用它(只是推出了第一个实例),所以希望它有效。
答案 1 :(得分:6)
如果您希望单独进行调试,WinDbg的SOS扩展可以为您提供此信息。
要运行的命令是“* ~e!clrstack”。
在正在运行的C#程序中,没有公开的方法来枚举托管线程或通过ID查找它们。即使你可以,在不同的线程上获得堆栈跟踪也可能需要暂停它,这有一些副作用的风险(请参阅为什么this is obsolete)。
另一种选择是在知道线程时登记线程,并在闲暇时扫描它们。这可能只有在您明确创建线程对象而不是使用线程池时才有可能。
尽管如此,我也很难看出这种方法的用途。如果是用于调试,则可以在内存或小型转储中执行更强大的技术。如果是用于日志记录,那么让日志记录调用贡献自己的堆栈可能是有意义的。
答案 2 :(得分:0)
您可以使用 ProcInsp,它有一个 Web API 来获取线程及其堆栈的 JSON。 Web API 可在 /Process/%PID%/Threads
使用(使用 GET
请求)。
免责声明:我是 ProcInsp 的开发者。该工具已获得 MIT 许可,可免费使用。
答案 3 :(得分:-1)
正如Mason of Words所暗示的那样,这在托管代码本身中看起来并不可行。 你能澄清一下你为什么需要这个:可能有更好的解决方案吗?
例如,如果在Visual Studio中附加到进程并按“暂停”,则“Threads”窗口将列出所有托管线程,“Stacktrace”窗口可以显示每个线程的当前堆栈跟踪。那就够了吗?
答案 4 :(得分:-2)
有一个StackTrace类
var trace = new System.Diagnostics.StackTrace(exception);
http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx
答案 5 :(得分:-6)
你可以在System.Diagnostics.Process.GetCurrentProcess()上循环。线程和每个线程创建一个带有.ctor的StackTrace对象,它以一个Thread作为它的参数。