In java it is possible to get a snapshot of the stacktraces of all running threads.
This is done with java.lang.Thread.getAllStackTraces()
(it returns Map
If you want this for debugging purposes alone, the SOS extensions to WinDbg can give you this information.
The command to run is "*~e !clrstack".
Inside of a running C# program, there is no public way to enumerate managed threads or look them up by ID. Even if you could, getting a stack trace on a different thread would likely require it to be suspended, which has some risks of side effects (see why this is obsolete).
The other alternative is to enlist threads as they are known, and scan them at your leisure. This is probably only possible if you're explicitly creating thread objects rather than using the thread pool.
That said, it is also hard for me to see what purpose this approach would serve. If it is for debugging, there are far more powerful techniques that can be done in-memory or on mini-dumps. If it is for logging, then it might make sense to have logging calls contribute their own stacks.
As Mason of Words suggests, this doesn't look possible from within the managed code itself. Could you clarify why you need this: there might be a better solution?
For example, if you attach to the process in Visual Studio and press "pause", then the "Threads" window will list all managed threads, and the "Stacktrace" window can show the current stack trace for each thread. Would that suffice?
So I actually just had to figure out how to do this -- haven't used this solution extensively in production yet, but theres a relatively new library called ClrMd.
http://blogs.msdn.com/b/dougste/archive/2013/05/04/clrmd-net-crash-dump-and-live-process-inspection.aspx
Using it, I'm able to attach to my own process and get a stack trace for all live threads. Using this when a deadlock is detected before restarting our app like so:
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);
The really important thing to get that to work from the same process is AttachFlag.Passive
If you just do DataTarget.AttachToProcess(pid, 5000)
, it'll do an "invasive" attach which attempts to pause the process. This throws an exception when you try to attach to your own process, I'm assuming because you can't pause your application while trying to attach from your application or something like that.
You can loop on System.Diagnostics.Process.GetCurrentProcess().Threads and for each Thread create a StackTrace object with the .ctor that takes a Thread as its param.
There is a StackTrace class
var trace = new System.Diagnostics.StackTrace(exception);
http://msdn.microsoft.com/en-us/library/system.diagnostics.stacktrace.aspx