【发布时间】:2021-09-16 21:16:15
【问题描述】:
我已经阅读了几个关于这个问题的讨论并设法理解了一点,但在从 Thread 类转换为 ThreadPool 类时仍然存在一些解决性能问题的问题
详情:
我已经构建了一个 tcp 服务器,用于教育目的(任务不应该使用异步方法),它接受客户端连接并为每个客户端创建一个新线程。使用这种方法,应用程序的执行时间不到一秒,但是当决定转移到像线程池这样的下一级解决方案时,我的性能下降到仅 100 个客户端的 40-50 秒,我只发送一个 2048 字节的缓冲区,接收它并关闭。
前 12 个线程非常快,很可能是因为我的 CPU 是 6 核 12 线程,然后线程开始出现延迟。我对解决方案的想法和结构方法持开放态度。
服务器代码:
public void OnSocketReceive()
{
while (!this.exitServer)
{
if (!tcpListener.Pending())
{
Thread.Sleep(10);
continue;
}
TcpClient client = tcpListener.AcceptTcpClient();
IManageConnectedUser chatLogic = new ManageConnectedUser(connections, welcomeMessage);
//Thread clientThread = new Thread(new ParameterizedThreadStart(chatLogic.OnClientConnection));
//clientThread.Start(client);
ThreadPool.QueueUserWorkItem(chatLogic.OnClientConnection, client);
}
更多说明
到目前为止,通过我所做的调试和阅读的讨论,我得出的结论是,问题出在 OnClientConnection 函数中的阻塞代码,更具体地说是在 stringCreateHandler 的内部函数中。我在哪里收到此错误: System.Threading.ThreadInterruptedException: 线程从第 39 行的等待状态中断,即 Thread.Sleep(10);
public string stringCreateHandler(TcpClient client)
{
StringBuilder sb = new StringBuilder();
try
{
do
{
if (client.Available > 0)
{
while (client.Available > 0)
{
char ch = (char)client.GetStream().ReadByte();
if (ch == '\r')
{
continue;
}
if (ch == '\n')
{
return sb.ToString();
}
sb.Append(ch);
}
}
Thread.Sleep(10);
} while (true);
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
我已经检查了其余的代码,我认为没有更多的阻塞代码,但我给出了项目的链接https://github.com/nikolaymih/Chat-Project/tree/master/ChatProjectNewThreads 唯一的区别是 Thread 类而不是 ThreadPool 但这只是为了定位
【问题讨论】:
-
使用异步方法,处理完成而不是轮询。使用
await可以轻松完成一些事情。说the task is not to use async methods毫无意义。 Windows 是一个异步操作系统。所有 IO 都是异步的,阻塞操作是模拟的。实际的 IO 不使用线程池线程,它是在驱动程序级别异步执行的。应用程序级别的额外操作由不同的 IO 线程池执行。 Kestrel 速度如此之快,因为它不会阻塞。 -
“记录并重新抛出”模式没有错...记录通常比打印到控制台更微妙,但这是一个玩具应用程序
-
你说
the task is not to use async methods但你也说I am open to solution ideas and structure approach这两个东西是矛盾的。在现代编程中正确的做法是使用async,所以你需要解释为什么你不想使用它 -
@Enigmativity OP 重新抛出异常——它没有被吞没。
-
@Enigmativity
throw e;会丢失它,但throw;不会
标签: c# .net multithreading performance threadpool