如何查看有多少线程正在完成我的任务TPL?

时间:2014-11-25 08:19:06

标签: c# .net multithreading task-parallel-library async-await

假设我想下载带有任务并行库的多个文件,现在我想要想象一下从VS2010 IDE调试时有多少线程工作?这是一个使用TPL下载许多文件的代码片段。

var list = new[] 
{ 
    "http://google.com", 
    "http://yahoo.com", 
    "http://stackoverflow.com" 
}; 

var tasks = Parallel.ForEach(list,
        s =>
        {
            using (var client = new WebClient())
            {
                Console.WriteLine("starting to download {0}", s);
                string result = client.DownloadString((string)s);
                Console.WriteLine("finished downloading {0}", s);
            }
        });

请引导我或将我重定向到我可以获取知识的任何文章,看看有多少线程正在运行以完成我的任务。

1 个答案:

答案 0 :(得分:2)

Parallel.ForEach将默认使用ThreadPool作为其基础线程池,除非您在传递实例ParallelOptions时另行指定(并传递自定义TaskScheduler)。您可以通过用ThreadPool.GetMaxThreads减去ThreadPool.GetAvailableThreads来监视线程池并查看当前正在使用的线程数,但是这将告诉您线程池当前正在使用许多线程,这不仅用于运行你当前的循环,但在你的程序中运行其他工作。

更具体地说,您可以使用Thread.CurrentThread.ManagedThreadId来获取当前正在执行的ThreadId

using (var client = new WebClient())
{
    Console.WriteLine("Currently running on thread id: {0}",
                       Thread.CurrentThread.ManagedThreadId);
    Console.WriteLine("starting to download {0}", s);
    string result = client.DownloadString((string)s);
    Console.WriteLine("finished downloading {0}", s);
}

现在,作为您的问题的旁注,进行IO绑定工作不需要使用任何线程,因为它本质上是异步的。这意味着使用Parallel.ForEach可能会导致使用线程池线程简单地阻止挂起的IO请求的开销更多。

您可以执行的操作是同时执行

string[] list = new[] 
{ 
    "http://google.com", 
    "http://yahoo.com", 
    "http://stackoverflow.com" 
}; 

using (WebClient client = new WebClient())
{
    var webRequestTasks = list.Select(address => client
                                                 .DownloadStringTaskAsync(address))
                                                 .ToList();
    await Task.WhenAll(webRequestTasks);
}

这种方式没有阻塞的线程,并且您的HTTP请求正在同时执行。