如何在.net 4.0中获取正在运行的任务列表

我正在尝试获取所有当前正在运行的任务的列表。 .net 4.0任务API是否提供此类function? 或者唯一的选择是明确地将任务存储在单独的集合中?

我想你需要TaskScheduler.GetScheduledTasks方法,但是:

  1. 它受到保护
  2. MSDN说它应该只用于调试
  3. 据我所知,此方法仅由ThreadPoolTask​​Scheduler实现,SynchronizationContextTaskScheduler始终返回null

所以我认为你应该尝试实现自己的TaskScheduler来实现你的目标。

创建任务时,默认情况下,任务计划在线程池线程上运行。 因此,您可以使用ThreadPool.GetMaxThreads和ThreadPool.GetAvailableThreads方法获取正在运行的任务数。

private static int GetWorkingThreads() { int maxThreads; int completionPortThreads; ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); int availableThreads; ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); return maxThreads - availableThreads; } 

为什么要查找正在运行的任务列表? 除了调试之外,您不必使用此信息。 在任何情况下,计划执行的任务列表与实际执行的任务之间存在差异。

正如Rusted所写,您可以从TaskScheduler.GetScheduledTasks方法获取计划任务的数量。 该方法是抽象的,因此必须由所有TaskSchedulers实现。

实际执行的任务数取决于TaskScheduler实现。 默认任务调度程序使用线程池 ,在这种情况下,应检查ThreadPool.GetAvailableThreads和ThreadPool.GetMaxThreads以估计执行任务的数量。

即使您使用默认的TaskScheduler,也没有正在运行的任务的实际列表。 调度程序基本上将任务分配给ThreadPool并将实际执行留给池(实际上,它调用Task.ExecuteEntry私有方法)。 它不需要保留正在运行的任务列表。

如果您希望将运行任务信息用于调试目的,则可以利用TPL中的事件跟踪Windows事件 。 遗憾的是,未记录任务已启动和任务已完成事件。 我在使用dotPeek浏览Task.ExecuteEntry的定义时找到了它们。

我发现有一篇文章探讨了TPL事件,但我不确定这是值得的。 除非你正在编写自己的调试器,否则看起来太麻烦了。

如果你只需要进入正在运行的任务列表,也许你应该编写自己的TaskScheduler并覆盖TryExecute和TryExecuteInternal来拦截每个任务的执行并将每个任务放在一个列表中。 这可能会变得昂贵,并且您必须定期进行一些清理以从列表中删除已完成的任务而不使用continuation(这将最终在列表中自己)。

MSDN上有一篇很好的文章http://msdn.microsoft.com/en-us/library/ms997649.aspx你所需要的一切都得到了很好的描述。

编辑:perhabs这将有助于:

 using System; using System.Diagnostics; class MainClass { public static void Main() { Process[] allProcs = Process.GetProcesses(); foreach(Process proc in allProcs) { ProcessThreadCollection myThreads = proc.Threads; Console.WriteLine("process: {0}, id: {1}", proc.ProcessName, proc.Id); foreach(ProcessThread pt in myThreads) { Console.WriteLine(" thread: {0}", pt.Id); Console.WriteLine(" started: {0}", pt.StartTime.ToString()); Console.WriteLine(" CPU time: {0}", pt.TotalProcessorTime); Console.WriteLine(" priority: {0}", pt.BasePriority); Console.WriteLine(" thread state: {0}", pt.ThreadState.ToString()); } } } }