【问题标题】:ThreadPool behavior and TCPListener线程池行为和 TCPListener
【发布时间】:2017-03-14 19:19:00
【问题描述】:

我像这样开始TCPListener,当工作完成后我关闭Socket。 我想知道我开始的Thread是不是这样

ThreadPool.QueueUserWorkItem(ConnectClientsThredProc, args);

会自我毁灭,所以我不需要任何外部控制。

如果我担心或不担心,谁能这么高兴地解释一下。 谢谢!

   class TCPListenerManager
    {
        TcpListener tcpListener;
        HostListenerItem hostListener;
        private bool _isServerWorking = false;

     public TCPListenerManager(HostListenerItem hostListenerItem)
     {
         hostListener = hostListenerItem;

         tcpListener = new TcpListener(IPAddress.Parse(hostListenerItem.IP4), hostListenerItem.Port);

         var t = Task.Factory.StartNew(async () =>
                {
                    await StartAsync(hostListenerItem.ClientsMax);
                });
            }

    public async Task StartAsync(int clientsMax)
    {
                    tcpListener.Start();
                    _isServerWorking = true;
                    for (int i = 0; i < clientsMax; i++)
                    {
                        if (_isServerWorking)
                        {
                            ServerConnectedEventArgs args = new ServerConnectedEventArgs();
                            args.TcpClient = await tcpListener.AcceptTcpClientAsync();
                            args.HostListener = hostListener;

                            OnServerConnected(args);
                            ThreadPool.QueueUserWorkItem(ConnectClientsThredProc, args);
                        }
   }
}


private void ConnectClientsThredProc(object obj)
{     
           var args = (ServerConnectedEventArgs)obj;

           if (args.TcpClient.Connected)
           {
              // Do some job and disconnect
              args.TcpClient.Client.Close();
              args.TcpClient.Client = null; 
           }
  }
}

【问题讨论】:

  • 线程会一直运行到它运行的方法退出
  • 但是你不应该像那样运行 tcp 连接线程。 queueuserworkitem 用于排队的后台任务。这不是您想要的,您现在需要处理连接。显式启动一个线程
  • 不,一旦该方法结束,线程就消失了
  • StartNew 不适用于异步,你真的应该使用 Task.Run( 代替。 (与您的问题无关,而是最佳实践问题)
  • 我刚才说,它不能解决你的问题,我只是警告你StartNew is dangerous

标签: c# .net threadpool tcplistener


【解决方案1】:

ConnectClientsThredProc 退出时,线程并没有“消失”而是返回到池中(这就是线程池首先存在的原因)。无论如何,您确实不应该关心这一点,除非您在ConnectClientsThredProc 中执行了长时间运行的任务。如果它长时间运行 - 最好不要使用线程池线程,而是启动一个新线程(例如通过Task.Factory.StartNew + TaskCreationOptions.LongRunning)。

此外,您可以在一小段代码中使用 Task.Factory、async\await、ThreadPool.QueueUserWorkItem,将所有这些混合在一起。也许您需要更好地了解这些工具是什么以及它们之间的异同(尤其是 async\await)。例如,这是什么原因:

var t = Task.Factory.StartNew(async () =>
{
      await StartAsync(hostListenerItem.ClientsMax);
 });     

您启动一个任务\线程,在其中启动另一个任务,然后等待它退出 - 没有什么意义。

您可以使用Task.Run 代替ThreadPool.QueueUserWorkItem 以达到相同的效果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 1970-01-01
    • 2011-09-29
    相关资源
    最近更新 更多