简单实现异步多线程TCP服务器。 以满足的方式工作,但内存使用量不断增加。 调查后我发现那个内存都是没有被清理的线程对象。 但是,线程确实将“主机断开连接”写入日志文件,因为这是该线程要执行的最后一行代码,所以我希望它自行清理。但是这似乎并没有发生。对于所做的每一个连接,都会创建一个线程并停止运行,但它永远不会完全清理。线程在完成执行后未被清除
这是怎么回事?
没有例外正在要么产生。
private void AcceptNextClient()
{
if (acceptConnections) serverSocket.BeginAcceptTcpClient(new AsyncCallback(AcceptTcpClientCallback), serverSocket);
}
private void AcceptTcpClientCallback(IAsyncResult ar)
{
try
{
TcpListener serverSocket = (TcpListener)ar.AsyncState;
TcpClient clientConnection = serverSocket.EndAcceptTcpClient(ar);
new Thread(unused => HandleClientCommunication(clientConnection)).Start();
}
catch (Exception ex) { Disk.AppendLog(ex.ToString()); }
AcceptNextClient();
}
private void HandleClientCommunication(TcpClient tcpClient)
{
string hostName = "";
try
{
using (StreamWriter sw = new StreamWriter(tcpClient.GetStream()))
using (StreamReader sr = new StreamReader(tcpClient.GetStream()))
{
hostName = Dns.GetHostEntry(((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address).HostName;
bool read = true;
while (read)
{
string buffer = sr.ReadLine();
if (buffer == null) read = false;
else
{
if (buffer.ToUpper().Equals("CLOSE_CONNECTION")) read = false;
else
{
sw.WriteLine(buffer);
sw.Flush();
}
}
}
tcpClient.Close();
}
}
catch (Exception ex)
{
Disk.AppendLog(hostName + " " + ex.ToString());
}
Disk.AppendLog("host disconnected");
}
public static void AppendLog(string msg)
{
File.AppendAllText(exePath + "errors.log", DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + " " + msg + Environment.NewLine);
}
“一个线程被创建并停止运行,但它永远不会完全清理。”究竟是什么让你得出这样的结论呢?并且说“因为记忆力增加”。你有没有试过内存分析器? –
是的,我尝试JetBrains .dotTrace,并且进程资源管理器有一个关于.NET性能的选项卡,.NET CLR LocksAndThreads,我可以清楚地看到客户端连接时线程对象的数量。当他们断开连接时永远不会退缩。在第一次启动该程序时,大约是7MB,但几天后它超过了100MB,并且仍在增长。做一个GC.Collect()也不会清理它们。 –
没有任何显示如果“主机已断开连接”已被写入,它将保持线程。我的怀疑是,没有任何内存压力让它值得做一个完整的收集。你尝试强制GC.Collect(GC.MaxGeneration,GCCollectionMode.Forced); GC.WaitForPendingFinalizers();'?注意:你不应该把它留在生产代码中 - 它只是帮助确定这是否是原因。 –