AFAIK .Net库中的一些方法能够异步执行 I / O作业而不消耗池中的线程。
如果我的信息是正确的, WebClient *异步方法可以做到这一点。
我想通过检查下载过程中是否有效地使用池中的线程来验证它。
所以我的一般问题是:如何监控线程池的当前状态?
线程数
忙线程数
是否有提供此信息的 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);
我正在比较:
有趣的部分是最后两部分。
我希望并尝试证明异步I / O是:
更快因为它们会减少对游泳池的压力(需要创建更少的线程......)
更轻,因为它们会消耗较少的游戏线程
我的“基准”显示它更快,我想这是因为池不需要为每个请求分配新线程,而使用PLINQ,每个并行请求将阻塞一个线程。
现在我想检查有关线程消耗的数字。
评论的任务是对监控池的不良尝试。这可能是一个很好的起点,但是直到现在结果并没有真正符合我的预期:它永远不会显示消耗超过3/4个线程,而我预计会有32个线程忙碌。
我愿意接受任何改进或更好的任何其他用例,以明确突出两种方法之间的差异。
希望现在更清楚了,很抱歉没有及早提供详细信息。 :)
答案 0 :(得分: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);