|
-
April 2nd, 2012, 03:22 AM
#1
[RESOLVED] Delegate, Invoke, Threads and anormal bug
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
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|