Hello everybody,

I'm doing a server with a form and to update the "console" I use delegates as my server class is different from the form class (have to be imported later). This function is called UpdateLog(String mymessage)

In the whole program I can call it as many times i want, no problem.
During the closing we have a big problem : the program frezzes on an update log. Here is a part of the code (I removed sensitives/useless parts)

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.Security.Cryptography;
using System.Net.Sockets;
using System.IO;

namespace Serveur
{
    public partial class FauxServeur : Form
    {
        // Variables d'état
        public bool bStartEnable = true;

        #region Update Log
        public delegate void DeleguePourUpdateLog(String message);

        private void UpdateLog(String s)
        {
            textBoxLog.AppendText(s);
        }

        public void StatusChanged(object sender, EventPourUpdateLog e)
        {
            this.Invoke(new DeleguePourUpdateLog(this.UpdateLog), new object[] { e.message });
            
        }
        #endregion

        public FauxServeur()
        {
            InitializeComponent();
            Serveur.StatusChanged += new StatusChangedEventHandler(StatusChanged);
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            if (bStartEnable)
            {
                textBoxIp.Enabled = false;
                textBoxPort.Enabled = false;
                if (Serveur.StartServer(textBoxIp.Text, int.Parse(textBoxPort.Text)))
                {
                    bStartEnable = false;
                    buttonStart.Text = "Déconnecter";
                }
                else
                {
                    textBoxIp.Enabled = true;
                    textBoxPort.Enabled = true;
                }
            }
            else
            {
                Serveur.Close();
                textBoxIp.Enabled = true;
                textBoxPort.Enabled = true;
                bStartEnable = true;
                buttonStart.Text = "Démarrer";
            }
        }

    }

    #region Délégué et classe evènement

    public delegate void StatusChangedEventHandler(object sender, EventPourUpdateLog e);

    public class EventPourUpdateLog : EventArgs
    {
        private String myMessage;
        public String message
        {
            get
            {
                return myMessage;
            }
            set
            {
                myMessage = value;
            }
        }

        public EventPourUpdateLog(String _mess)
        {
            myMessage = _mess;
        }
    }

    #endregion
    
    static class Serveur
    {
        // Variables pour l'update du log
        private static EventPourUpdateLog e;
        public static event StatusChangedEventHandler StatusChanged;
        /// <summary>
        /// ATTENTION : Cette fonction ne rajoute pas le Environment.NewLine * la fin
        /// </summary>
        /// <param name="Message"></param>
        public static void UpdateLog(String Message)
        {
            e = new EventPourUpdateLog(Message);
            OnStatusChanged(e);
        }
        private static void OnStatusChanged(EventPourUpdateLog e)
        {

            Delegate d = StatusChanged.GetInvocationList()[0];
            d.DynamicInvoke(new object[] { null, e });

            return;
            
            StatusChangedEventHandler statusHandler = StatusChanged;
            if (statusHandler != null)
            {
                // Invoque le délégué
                statusHandler(null, e);
                 //statusHandler.DynamicInvoke(null, e);
            }
        }

        // Infos sur le serveur
        private static IPAddress myIp;
        private static int myPort;
        private static IPEndPoint myEndPoint;
        private static TcpListener myListener;
        private static Thread myThreadListener;
        private static Thread myThreadManager;
        private static List<Client> myListClient;

        // Cryptage de l'envoi des clés
        private static DESCryptoServiceProvider desKeysExchange;
        public static ICryptoTransform encryptor;

        // Variables d'état
        private static bool bListenerEnable = false;
        private static bool bServerEnable = false;
        private static bool bShutdownInitiated = false;
        private static ManualResetEvent ConnexionAcceptee = new ManualResetEvent(false);
        private static ManualResetEvent FermetureComplete = new ManualResetEvent(false);
        private static ManualResetEvent FermetureListener = new ManualResetEvent(false);

        public static bool StartServer(String ip, int port)
        {
            UpdateLog("[INFO] Vérification des paramètres." + Environment.NewLine);
            bool bOk = true;
            if (!IPAddress.TryParse(ip, out myIp))
            {
                bOk = false;
                UpdateLog("[ERREUR] Adresse IP incorrecte." + Environment.NewLine);
            }
            if (port > 65535 || port < 1)
            {
                bOk = false;
                UpdateLog("[ERREUR] Port incorrect. Le port doit être compris entre 1 et 65534." + Environment.NewLine);
            }
            if (bOk)
            {
                myListClient = new List<Client>();
                myIp = IPAddress.Parse(ip);
                myPort = port;
                myEndPoint = new IPEndPoint(myIp, myPort);


                UpdateLog("[INFO] Préparation du crypteur" + Environment.NewLine);
                desKeysExchange = new DESCryptoServiceProvider();
                desKeysExchange.Key = bytesDesKeyExchangeKey;
                desKeysExchange.IV = bytesDesKeyExchangeIV;
                encryptor = desKeysExchange.CreateEncryptor();



                UpdateLog("[INFO] Vérification terminée. Connexion * : " + myEndPoint.ToString() + Environment.NewLine);
                UpdateLog("[INFO] Ouverture du port d'écoute." + Environment.NewLine);
                myListener = new TcpListener(myEndPoint);
                bServerEnable = true;
                bListenerEnable = true;
                myThreadManager = new Thread(new ThreadStart(ManagerLoop));
                myThreadManager.Start();
                myThreadListener = new Thread(new ThreadStart(ListenerLoop));
                myThreadListener.Start();
                return true;
            }
            else
            {
                return false;
            }
        }

        private static void ListenerLoop()
        {
            try
            {
                UpdateLog("[INFO] Démarrage du serveur" + Environment.NewLine);
                myListener.Start();
                while (bListenerEnable)
                {
                    //UpdateLog("[INFO] En attente de clients" + Environment.NewLine);
                    if (myListener.Pending())
                    {
                        //ConnexionAcceptee.Reset();
                        TcpClient tc = myListener.AcceptTcpClient();
                        Client c = new Client(tc);
                        UpdateLog("[INFO] Nouveau client" + Environment.NewLine);
                        myListClient.Add(c);
                        //ConnexionAcceptee.WaitOne();
                    }
                }
                UpdateLog("[INFO] Fermeture listener" + Environment.NewLine);     
                Console.WriteLine("1");
                myListener.Stop();
                Console.WriteLine("2");
                UpdateLog("[INFO] Listener fermé" + Environment.NewLine);    //here it crashes, when this line is commented everything is fine, else it crashes randoly
                Console.WriteLine("3");
                //FermetureListener.Set();
            }
            catch (ThreadAbortException)
            {
                UpdateLog("[INFO] Abort sur listener reçu" + Environment.NewLine);
                myListener.Stop();
                //UpdateLog("[INFO] Fermeture listener sur Abort request" + Environment.NewLine);
                //FermetureListener.Set();
            }
        }

        private static void ManagerLoop()
        {
            UpdateLog("[INFO] Démarrage du manager" + Environment.NewLine);
            while (bServerEnable)
            {
                List<Client> DeletionList = new List<Client>();
                if (myListClient.Count != 0)
                {
                    foreach (Client c in myListClient)
                    {
                        if (c.bMarkedForDeletion || bShutdownInitiated)
                        {
                            c.Close();
                            DeletionList.Add(c);
                        }
                    }
                }
                if (DeletionList.Count != 0)
                {
                    foreach (Client c in DeletionList)
                    {
                        myListClient.Remove(c);
                    }
                }
                if (!bShutdownInitiated)
                {
                    Thread.Sleep(Constants.ManagerThreadPauseTime);
                }
                else
                {
                    bServerEnable = false;
                    //FermetureComplete.Set();
                }
            }
        }

        public static void Send(String message)
        {
            UpdateLog("[INFO] Envoi du message suivant : " + Environment.NewLine);
            UpdateLog(message + Environment.NewLine);
            if (myListClient != null)
            {
                if (myListClient.Count != 0)
                {
                    foreach (Client c in myListClient)
                    {
                        c.SendData(message);
                    }
                }
                else
                {
                    UpdateLog("[AVERTISSEMENT] Aucun client connecté, envoi du message annulée" + Environment.NewLine);
                }
            }
            else
            {
                UpdateLog("[ERROR] Le serveur n'est pas initialisé" + Environment.NewLine);
            }
        }

        public static void Close()
        {
            FermetureComplete.Reset();
            FermetureListener.Reset();
            UpdateLog("[INFO] Shutdown in progress" + Environment.NewLine);
            // C'est le manager qui va fermer tout le monde
            bListenerEnable = false;
            //ConnexionAcceptee.Set();
            bShutdownInitiated = true;
            //FermetureComplete.WaitOne();
            //FermetureListener.WaitOne();

            //myThreadListener.Abort();
            if (myThreadListener.IsAlive)
            {
                //UpdateLog("[INFO] Attente fermeture listener" + Environment.NewLine);
                myThreadListener.Join();
            }

            // Normalement le manager est déj* fermé !
            myThreadManager.Abort();
            if (myThreadManager.IsAlive)
            {
                UpdateLog("[INFO] Attente fermeture manager" + Environment.NewLine);
                myThreadManager.Join();
            }

            UpdateLog("[INFO] Fermeture terminée" + Environment.NewLine);
        }

    }

}
Problematic section is in blue

The outputs is as fellow : The thread '<No Name>' (0x1bec) has exited with code 0 (0x0).
1
2

The button goes through 2 states : start, disconnect

1) Start : OK
2) Disconnect : 50 % chance freeze
3) (if it didn't freeze) Start : OK
4) Disconnect : 100% chance freeze