비동기 멀티 스레드 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();'? 참고 : 프로덕션 코드에 그대로두면 안됩니다. 단순히 이것이 원인인지 여부를 식별하는 데 도움이됩니다. –