线程池的线程仿佛用完了

线程池的线程好像用完了
我的程序是用tcpclient与几十台下位机通讯。在论坛大神的帮助下,程序写成了这个样子。

 private void frmMain_Load(object sender, EventArgs e)
{
proc();
}
private void proc()
        {
            timer = new System.Threading.Timer(h =>
            {
                if (enableComm)
                {
                    foreach (var s in Session.Stations)
                    {
                        var station = Session.Stations.Find(p => p.Id == s.Id);
                        if (station.IsWorking == true)
                        {
                            if (!comm.COMMStates.ContainsKey(station.Id))
                            {
                                comm.COMMStates[station.Id] = new COMMState()
                                {
                                    Station = station,
                                    Data = new byte[250],
                                    StationErrNum = 0,
                                    Exception = null,
                                    TcpClient = null
                                };
                            }
                            ThreadPool.QueueUserWorkItem(x => ThreadPollCallback(comm.COMMStates[station.Id]));
                        }
                    }
                }
                
            },null,0,1000);
            
        }
 public void ThreadPollCallback(object state)
        {
            var cs = state as COMMState;
            if (cs == null) return;
            var station = cs.Station;

           //防止在connect 过程中再次连接,因为下位机只允许3个连接
            if (cs.COMMUNICATION_STATE == COMMUNICATIONSTATE.连接&&cs.TriesNum>=3)
            {
                lock (lockObj)
                {           
                    cs.Exception = new Exception("communication timeout");                   
                }               
                return;
            }
            cs.Thread = Thread.CurrentThread;
            try
            {                
              //连接
                if (cs.TcpClient == null || !cs.TcpClient.Connected)
                {
                    lock (lockObj)
                    {
                        cs.COMMUNICATION_STATE = COMMUNICATIONSTATE.连接;
                        cs.TriesNum++;
                    }                    
                    cs.TcpClient = new TcpClient(cs.Station.IP, 502);
                }
                TcpClient tc = cs.TcpClient;
                lock (lockObj)
                {
                    cs.COMMUNICATION_STATE = COMMUNICATIONSTATE.开始;
                }          
               //读数据,实际就是write之后read      
                ModbusIpMaster master = ModbusIpMaster.CreateIp(tc);
                ushort startAddress = 0;
                ushort numInputs = 125;
                ushort[] res = master.ReadHoldingRegisters(startAddress, numInputs);
                lock (lockObj)
                {
                    //处理数据,保存到数据库
                   cs.COMMUNICATION_STATE = COMMUNICATIONSTATE.完成;
                }
            }
            catch (Exception e)
            {
                cs.COMMUNICATION_STATE = COMMUNICATIONSTATE.故障;
            }
            finally
            {

            }
        } 

现在的问题是,程序运行一个多小时后,通讯就会中断,断点发现这时候程序根本就不执行ThreadPollCallback,而且整个程序变得非常慢,感觉就像是线程池已经用完了,再有新的线程也不理会一样。
我猜想可能与tcp连接失败有关。
因为下位机中经常有一些没有连到网络,所以有一些线程是在不断重复“connect,失败”的过程。看上去这个过程每秒都要新开一个线程来做,而且旧的线程并不会被回收。
求助,这个问题怎么办啊?
------解决思路----------------------
引用:
Quote: 引用:

ThreadPool.QueueUserWorkItem本身就是返回一个bool值的,返回true代表分配成功
重复connect失败,开新线程也还是这样而已……


为了保证某个时候某台下位机恢复网络后能马上开始通讯,所以每次都要试着去连一下,哪怕重复失败。

就你这一句话,就知道你的线程池为啥满了……
你为啥要开新线程去判断是否能通讯呢?为什么不能再fail后再此线程内继续连接呢?
------解决思路----------------------
引用:
防止重入也有问题,因为操作实际上是write之后等回复,现在就是write完之后read,如果下位机不回复就会一直等着。这时候只好重入一下,再write一次试试。

设置超时时间啊,超时了还没有回复,就别等了

我多次用收快递来打比方.

你从网上订购东西,就相当于是发送请求

你要接收数据,就好比是等快递.

等快递有很多种办法,
1.异步的方式就是快递来了放门卫,门卫给你打电话,然后你去取.
当然快递一直不来,门卫就一直不给你打电话,你需要自己设置个定时器,判断时间太长了怎么还没到,然后自己打电话去催.

2.同步的方式就是你订货之后,就没事去门卫那里溜达溜达,看看货到是没到.

而你现在就是用同步的思想来做.
同步的思想再加上线程池的概念,就是你自己不去看,而是派个人去看.
而你没告诉派去的人要等多长时间还不来就回来,而是没来就一直在那里等.

然后你又在时间过长之后,又派新的人去看.

导致门卫那里堵了一大堆人都在帮你等快递,这有任何意义??
------解决思路----------------------
设置ReceiveTimeout之后,如果超时了还没有数据到达,就会报个错误,进入catch