在java中,可以獲得所有正在運行的線程的堆棧跟蹤的快照。 這是通過java.lang.Thread.getAllStackTraces()完成的(它返回Map < Thread,StackTraceElement [] >)。有沒有辦法讓c#中的所有線程的堆棧跟蹤,如java.lang.Thread.getAllStackTraces()?
如何用.net做同樣的事情?
在java中,可以獲得所有正在運行的線程的堆棧跟蹤的快照。 這是通過java.lang.Thread.getAllStackTraces()完成的(它返回Map < Thread,StackTraceElement [] >)。有沒有辦法讓c#中的所有線程的堆棧跟蹤,如java.lang.Thread.getAllStackTraces()?
如何用.net做同樣的事情?
所以我實際上只是想知道如何做到這一點 - 在生產中還沒有廣泛使用這個解決方案,但是一個相對較新的庫叫做ClrMd。
使用它,我能夠連接到我自己的進程,並得到一個堆棧跟蹤所有活動線程。使用檢測到死鎖時,這樣重新啓動我們的應用程序,像這樣前:
var result = new Dictionary<int, string[]>();
var pid = Process.GetCurrentProcess().Id;
using (var dataTarget = DataTarget.AttachToProcess(pid, 5000, AttachFlag.Passive))
{
string dacLocation = dataTarget.ClrVersions[0].TryGetDacLocation();
var runtime = dataTarget.CreateRuntime(dacLocation);
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)
,它會做試圖暫停過程的「入侵」附加。當您嘗試附加到您自己的進程時,這會引發異常,我假設您因爲無法在嘗試從應用程序或類似應用程序中附加時暫停應用程序。
無論如何,是的,很酷的東西。
如果任何人有任何理由爲什麼這是超級天真或任何東西,pleeeeease指出。尚未在生產中使用它(只是推出第一個例子),所以希望它的工作。
剛從客戶端找回了一些調試轉儲,這對我們很有用。很酷。 – 2014-07-09 20:02:28
偉大的代碼,謝謝!我可以建議像f.Method.GetFullSignature()一樣添加方法簽名。它可能會有幫助的情況下,覆蓋 – Andrey 2014-07-14 04:51:35
只是一個更新 - 我從這個從相當大數量的客戶端安裝得到的結果,它一直工作,並得到體面的幫助。 – 2015-03-15 17:53:01
有一個堆棧跟蹤類
var trace = new System.Diagnostics.StackTrace(exception);
http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx
您可以循環在System.Diagnostics.Process.GetCurrentProcess()線程和每個線程的創建,是以.ctor堆棧跟蹤對象一個線程作爲它的參數。
與@ MarcosMeli的回答一樣,這是不正確的。正如@Hans Loken所述,GetCurrentProcess()方法返回一個包含ProcessThread對象而不是Thread對象的ProcessThreadCollection。據我所知,不能從ProcessThread中獲取堆棧跟蹤,因爲它代表Windows本地線程。 – 2010-11-24 14:13:38
試試這個
var proc = System.Diagnostics.Process.GetCurrentProcess();
var threads = proc.Threads;
var res = new Dictionary<Thread, StackTrace>();
foreach (Thread thread in threads)
{
var stackTrace = new StackTrace(thread, true);
res.Add(thread, stackTrace);
}
在水庫u得到與ü希望:)
運行該代碼會爲我引發InvalidCastException。 Process.Threads返回一個包含ProcessThread對象而不是Thread對象的ProcessThreadCollection。 此外,無法將ProcessThread轉換爲線程,因爲ProcessThread表示線程爲.net線程時的OS線程。 – 2010-02-25 09:55:39
映射字典如果你想要這個單獨調試目的,SOS擴展WinDbg中可以給你這個信息。
要運行的命令是「*〜e!clrstack」。
在正在運行的C#程序中,沒有公共方法來枚舉託管線程或按ID查找它們。即使可以,在另一個線程上獲取堆棧跟蹤也可能需要暫停,這有一些副作用的風險(請參閱this is obsolete)。
另一種選擇是在已知的線程中加入線索,並在閒暇時進行掃描。這可能只有在您明確創建線程對象而不是使用線程池時纔有可能。
也就是說,我很難看出這種方法的用途。如果是用於調試,那麼可以在內存或小型轉儲中使用更強大的技術。如果是用於日誌記錄,那麼讓日誌記錄調用貢獻自己的堆棧可能是有意義的。
正如Mason of Words所言,從託管代碼本身來看,這看起來不太可能。 你能否澄清爲什麼你需要這個:可能有更好的解決方案?例如,如果您在Visual Studio中附加進程並按「暫停」,則「線程」窗口將列出所有託管線程,「堆棧跟蹤」窗口可顯示每個線程的當前堆棧跟蹤。這足夠嗎?
你想對線程做什麼? – Simon 2011-01-25 00:12:22