简单实现异步多线程TCP服务器。 按预期工作,除了内存使用量持续上升。 调查后我发现那个内存都是没有被清理的线程对象。 但是,线程会写入" host disconnected"到日志文件,因为那是该线程执行的最后一行代码,我希望它能够自行清理。但这似乎并没有发生。对于每个建立的连接,创建一个线程并停止运行,但它永远不会完全清理。
发生了什么事?
也没有生成例外。
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);
}
答案 0 :(得分:0)
我猜这里是你使用像这样的线程
new Thread(unused => HandleClientCommunication(clientConnection)).Start();
}
如果你让我们假设每秒100次调用你最终会在你的应用程序中增加100 MB,因为每个线程需要1MB至少记住垃圾收集器不能保证即使线程也会一直收集内存已完成执行。
我在这里建议的是切换所有代码以使用任务
你的代码看起来像这样
Task.Factory.StartNew(unused => HandleClientCommunication(clientConnection));
}
这就是为什么你应该使用任务而不是线程(当它可能时)
答案 1 :(得分:0)
所以我发现答案后,注意到垃圾收集器在程序作为服务运行时无法运行,但在作为表单运行时运行(并解决所有内存问题)。
删除Main(string [] args)中的[STAThread]修复了所有问题。代码本身没有任何问题。