簡單實現異步多線程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();'?注意:你不應該把它留在生產代碼中 - 它只是幫助確定這是否是原因。 –