Markus
Markus

Reputation: 3627

how to get a list of running tasks in .net 4.0

I'm trying to get a list of all currently running tasks. Does the .net 4.0 tasks api provide such functionality? Or the only option is explicitly to store tasks in a separate collection?

Upvotes: 10

Views: 23551

Answers (5)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131180

Why would you want to find the list of running tasks? Apart from debugging, you shouldn't have to use this information. In any case, there is a difference between the list of the tasks that are scheduled for execution and the tasks that are actually executing.

As Rusted writes, you can get the number of scheduled tasks from the TaskScheduler.GetScheduledTasks method. The method is abstract so it has to be implemented by all TaskSchedulers.

How many tasks actually execute depends on the TaskScheduler implementation. The default task scheduler uses the threadpool, in which case you should check ThreadPool.GetAvailableThreads and ThreadPool.GetMaxThreads to approximate the number of executing tasks.

There is no actual list of running tasks, even when you use the default TaskScheduler. The scheduler essentially assigns a task to a ThreadPool and leaves the actual execution to the pool (actually, it calls the Task.ExecuteEntry private method). It has no need to keep a list of the running tasks.

If you want the running task information for debugging purposes, you can take advantage of the Event Trace for Windows events in TPL. Unfortunately, the Task Started and Task Finished events are not documented. I found them while browsing the definition of Task.ExecuteEntry with dotPeek.

I've found one article exploring the TPL events but I'm not sure it's worth the trouble. Unless you are writing your own debugger, it seems too much trouble.

If you just have to get to the list of running tasks, perhaps you should write your own TaskScheduler and override TryExecute and TryExecuteInternal to intercept the execution of each task and place each task in a list. This could get expensive though, and you would have to do some cleanup periodically to remove completed tasks from the list without using continuations (which would end up in the list themselves).

Upvotes: 1

Elo
Elo

Reputation: 2352

@HelgeJensen proposed a working solution on : How can I monitor the Task queues in the .NET TaskSchedulers (across AppDomain)

Microsoft discourage the use of GetScheduledTasksForDebugger Method :

This method is not thread safe and you shouldn't use it concurrently with other instances of TaskScheduler. Call this method from a debugger only when the debugger has suspended all other threads.

I tested the proposed solution and it works, even if we would likely encounter crashes using that in production code :

public static class ScheduledTaskAccess
{
    public static Task[] GetScheduledTasksForDebugger(TaskScheduler ts)
    {
        var mi = ts.GetType().GetMethod("GetScheduledTasksForDebugger", BindingFlags.NonPublic | BindingFlags.Instance);
        if (mi == null)
            return null;
        return (Task[])mi.Invoke(ts, new object[0]);
    }      
}

Usage:

    Task[] tasks = GetScheduledTasksForDebugger(TaskScheduler.Current);
    int count = tasks.Length;

And we could see the Status of each Task: Obtained list of Tasks

Upvotes: 2

Rusted
Rusted

Reputation: 619

I suppose you need TaskScheduler.GetScheduledTasks method, but:

  1. It's protected
  2. MSDN says it should be used only for debugging
  3. As far as I know this method has implemented only by ThreadPoolTaskScheduler, SynchronizationContextTaskScheduler always returns null

So I think you should try to implement own TaskScheduler to achieve your goals.

Upvotes: 5

Unril
Unril

Reputation: 106

When you create a Task, by default the task is scheduled to run on a thread pool thread. So, you can get number of running tasks by using ThreadPool.GetMaxThreads and ThreadPool.GetAvailableThreads methods.

    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;
    }

Upvotes: 2

HW90
HW90

Reputation: 1983

There is a good article on the MSDN http://msdn.microsoft.com/en-us/library/ms997649.aspx Everything you need is described very well.

Edit: perhabs this will help:

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()); 
         }
      }
   }
}

Upvotes: 0

Related Questions