实施线程池后的 Tcp Server 性能问题

Tcp Server performance issues after implementing thread pool

我已经阅读了一些关于此事的讨论并设法理解了一点,但是在解决从 Thread class 转换为 ThreadPool class 时的性能问题时仍然存在一些问题

详情:

我已经构建了一个 tcp 服务器,用于教育目的(任务不应该使用异步方法),它接受客户端连接并为每个客户端创建一个新线程。使用这种方法,应用程序的执行时间不到一秒,但是当决定移动到线程池等下一级解决方案时,我的性能下降到 40-50 秒,只有 100 个客户端,我只发送一个 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;
        }

    }

我检查了其余代码,我认为没有更多的阻塞代码,但我给项目 link https://github.com/nikolaymih/Chat-Project/tree/master/ChatProjectNewThreads 唯一的区别是 Thread class 而不是 ThreadPool 但这只是为了定位

查看您的完整项目,我认为您的问题是 OnClientConnection 很长-运行:在连接关闭之前它不会 return,因为这是一个“聊天应用程序”,连接保持打开状态,不会很快关闭。

如您所见,ThreadPool 从许多空闲线程开始,它会根据需要以大约每 500 毫秒一个的速率添加线程(尽管这是一个实现细节)。这通常不是问题:您不应该将 ThreadPool 用于非常长的 运行 任务,这些任务永远不会 return,并且永远占用线程。但是,由于您的 OnClientConnection 方法不会 return 多年,您只是在抢占 ThreadPool 线程,并迫使 ThreadPool 继续扩展。

如果您想为每个客户端使用一个线程,您最好为每个客户端创建一个新的 long-运行 线程。然而,这是非常浪费的:您将有大量的线程闲置而不做太多事情。最好有少量线程不断处理来自大量客户端的消息。可以自己构建它,但是使用 TcpListenerNetworkStream.

的 async/await 功能要容易得多