假设我想下载带有任务并行库的多个文件,现在我想要想象一下从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);
}
});
请引导我或将我重定向到我可以获取知识的任何文章,看看有多少线程正在运行以完成我的任务。
答案 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请求正在同时执行。