【发布时间】:2013-01-15 10:19:52
【问题描述】:
关于这个问题已经进行了很多讨论,但它们似乎无法解释我的特定问题。 我在使用 ThreadPool 而不是 Thread 类进行线程处理时遇到了严重的性能问题。
详情:
我已经构建了一个 tcp 服务器,当 tcp 服务器接受一个新客户端时,它会生成一个新线程来处理该客户端。一切都相当简单,但是我的服务器处理许多并发客户端的时间太长了。大约 35 个简单的客户端只发送 2048 字节的缓冲区,接收并关闭它,需要 30 秒。
经过多次停止后,我发现ThreadPool.QueueUserWorkItem 最多需要 26 秒。我用它来产生新的线程来处理新的客户。
将ThreadPool.QueueUserWorkItem 替换为new Thread() 后,我的性能提高到不到一秒。
我很想解释一下为什么会这样。
澄清:
延迟与客户端代码无关,从调用ThreadPool.QueueUserWorkItem到clientMsgHandler.HandleIncomingMsgs启动20秒可以过去。
延迟从第一个线程开始,实际上随着测试的继续略有改善。我对解决方案不太感兴趣,而对解释为什么会发生更感兴趣。 客户端确实会阻塞,但时间很短。
服务器代码:
private void AddTcpClientMsgHandler(TcpClient tcpClient)
{
//lock so no addition of client and closure can occur concurrently
Stopwatch watch = new Stopwatch();
watch.Start();
Monitor.Enter(this);
int pWatchIdx = watchIDX++;
if (!isOpen)
throw new ObjectDisposedException(ResourceAlreadyClosed);
TcpClientMsgHandler clientMsgHandler = CreateClientHandler(tcpClient);
clientMsgHandlerManager.AddTcpClientMsgHandler(clientMsgHandler);
//ThreadPool.QueueUserWorkItem(clientMsgHandler.HandleIncomingMsgs); takes 20 seconds to run
Thread thread = new Thread(clientMsgHandler.HandleIncomingMsgs);
thread.Start();
watch.Stop();
Monitor.Exit(this);
Console.WriteLine(string.Format("Iteration {0} took {1} Client {2}", pWatchIdx.ToString(),watch.Elapsed, tcpClient.Client.RemoteEndPoint));
}
【问题讨论】:
-
尝试使用像Red Gate's ANTS Performance Profiler这样的性能分析器。
-
你可能是线程池上的线程用完了吗?
-
一般诊断是您的 HandleIncomingMsgs() 方法花费的时间太长。顺便说一句,在 finally 块中不使用 Monitor.Exit() 是一个严重的错误。
-
为什么不将 TPL 的 Task.Factory.StartNew 方法与具有设置并发级别的自定义 TaskScheduler (msdn.microsoft.com/en-us/library/dd781658(v=vs.100).aspx) 一起使用?
-
Rudi,不,我正在使用功能强大的计算机,并且打开的线程少于 100 个。汉斯,这并不需要很长时间,实际上只需要不到一毫秒。但是感谢关于最后我会这样做的评论,以防万一。麦克斯,我去看看。
标签: c# .net multithreading performance threadpool