如何跟踪.Net线程池使用情况?

Pra*_*eek 8 .net c# multithreading threadpool

AFAIK .Net库中的一些方法能够异步执行I/O作业而不消耗池中的线程.

如果我的信息是正确的,WebClient*Async方法就是这样做的.

我想通过检查下载过程中是否有效地使用池中的线程来验证它.

所以我的一般问题是:如何监控线程池的当前状态?

  • 线程数

  • 忙线程数

是否有一些API(GetAvailableThreads?)或性能计数器可以提供此信息?


编辑:这里有一些更多的细节

我正在为教育目的写一个简单的基准:

string[] urls = Enumerable.Repeat("http://google.com", 32).ToArray();
/*{
    "http://google.com",
    "http://yahoo.com",
    "http://microsoft.com",
    "http://wikipedia.com",
    "http://cnn.com",
    "http://facebook.com",
    "http://youtube.com",
    "http://twitter.com"
};*/

/*Task.Run(() =>
    {
        while (true)
        {
            int wt, cpt;
            ThreadPool.GetAvailableThreads(out wt, out cpt);
            Console.WriteLine("{0} / {1}", wt, cpt);
            Thread.Sleep(100);
        }
    });*/

WebClient webClient = new WebClient();
Stopwatch stopwatch = Stopwatch.StartNew();
foreach (string url in urls)
{
    webClient.DownloadString(url);
    Console.WriteLine("Got '{0}'", url);
}
stopwatch.Stop();

TimeSpan sequentialTime = stopwatch.Elapsed;

stopwatch.Restart();
CountdownEvent cde = new CountdownEvent(1);
foreach (string url in urls)
{
    cde.AddCount();
    webClient = new WebClient();
    webClient.DownloadStringCompleted += (_, __) =>
    {
        Console.WriteLine("Got '{0}'", __.UserState);
        cde.Signal();
    };
    webClient.DownloadStringAsync(new Uri(url), url);
}
cde.Signal();
cde.Wait();
stopwatch.Stop();

TimeSpan asyncTime = stopwatch.Elapsed;

stopwatch.Restart();
ThreadLocal<WebClient> threadWebClient = new ThreadLocal<WebClient>(() => new WebClient());
urls.AsParallel().WithDegreeOfParallelism(urls.Length).ForAll(url => threadWebClient.Value.DownloadString(url));
stopwatch.Stop();

TimeSpan PLinqTime = stopwatch.Elapsed;

Console.WriteLine("Sequential time: {0}.", sequentialTime);
Console.WriteLine("PLinq time: {0}.", PLinqTime);
Console.WriteLine("Async time: {0}.", asyncTime);
Run Code Online (Sandbox Code Playgroud)

我在比较:

  • 天真的顺序循环
  • PLINQ循环
  • 异步I/O.

有趣的部分是最后两个.

我期望并尝试证明异步I/O是:

  • 更快,因为它们会减少对池的压力(需要创建更少的线程......)

  • 更轻,因为它们会消耗更少的游泳池线程

我的"基准"显示它更快,我想这是因为池不需要为每个请求分配新线程,而使用PLINQ,每个并行请求将阻塞一个线程.

现在我想检查有关线程消耗的数字.

评论的任务是监控池的不良尝试.这可能是一个很好的起点,但是直到现在结果与我的预期并不完全一致:它永远不会显示消耗超过3/4个线程,而我预计会有32个线程忙.

我愿意接受任何想法来增强它或更好的任何其他用例,这将明确突出两种方法之间的差异.

希望现在更清楚了,很抱歉没有尽快提供详细信息.:)

JTW*_*JTW 2

ThreadPool 类提供了 GetAvailableThreads 方法,该方法“检索 GetMaxThreads 方法返回的最大线程池线程数与当前活动线程数之间的差异”。[1]:http://msdn.microsoft.com/en-us/library/system.threading.threadpool.getavailablethreads%28v=vs.110%29.aspx

您可以这样捕获比率:

        int workerThreads;
        int completionPortThreads;
        ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
        Console.WriteLine("{0} of {1} threads available", workerThreads, completionPortThreads);
Run Code Online (Sandbox Code Playgroud)