Q:

Threads not being cleaned up after they finish execution

Simple implementation of an asynchronous multithreaded TCP server.
Works as intented, except, memory usage keeps going up.
After investigating I found that that memory were all thread objects not being cleaned up.
However, the threads do write "host disconnected" to the log file, and since that's the last line of code for that thread to execute I expect it to clean up itself. But that doesn't seem to be happening. For each and every connection that is made, a thread is created and stops running but it but never completely cleans up. 
What is going on?
No exceptions are being generated either.
    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);
    }

A:

So I found the answer, after noticing the Garbage Collector wasn't ever able to run while the program was being run as a service but did run (and solve all memory issues) when it was running as a Form.
Removing the [STAThread] at Main(string[] args) fixed all the issues. There wasn't anything wrong with the code itself.
http://support.microsoft.com/kb/828988

