none
Programm fährt nicht herunter RRS feed

  • Frage

  • Hallo,

    in folgendem Programm wird obwohl stop auf true gesetzt wird nicht gestoppt:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    namespace Instant_Messager_Server
    {
        class Program
        {
            static void Main(string[] args)
            {
                Function MainFunction = new Function();
                Thread ListenThread = new Thread(new ThreadStart(MainFunction.Listen));
                Thread RunThread = new Thread(new ThreadStart(MainFunction.Run));
                ListenThread.Start();
                RunThread.Start();
                Console.WriteLine("Willkommen im Server.\nEs werden verschiedene Benachrichtigungen in der Console angezeigt.\nstop zum beenden");
                string cmd = "";
                while(MainFunction.stop == false)
                {
                    cmd = Console.ReadLine();
                    if(cmd.ToLower() == "stop")
                    {
                        MainFunction.stop = true;
    
                    }
                    else
                    {
                        Console.WriteLine("Unbekannter Befehl.");
                    }
                }
                MainFunction.stop = true;
                Console.WriteLine("Fahre runter.");
               
            
            }
        }
    }
    namespace Instant_Messager_Server
    {
     
    
    
        class Function
        {
            List<BasicUser> reguser = new List<BasicUser>();
            List<BasicUser> onlineuser = new List<BasicUser>();
            List<BasicTask> tasks = new List<BasicTask>();
            public bool stop = false;
            static int port = 80;
            TcpListener listener = new TcpListener(IPAddress.Any, port);
            public void Run()
            {
                do
                {
                   if(!tasks.Any())
                    {
    
                    }
                    
    
                    
                    else if (tasks[0] is RegisterTask)
                    {
                        Register(tasks[0] as RegisterTask);
                        tasks.RemoveAt(0);
                    }
                    else if (tasks[0] is LoginTask)
                    {
                        Login(tasks[0] as LoginTask);
                        tasks.RemoveAt(0);
                    }
                    else if (tasks[0] is LogoutTask)
                    {
                        Logout(tasks[0] as LogoutTask);
                        tasks.RemoveAt(0);
                    }
                    else if (tasks[0] is MessageTask)
                    {
                        MessageTask task = tasks[0] as MessageTask;
                        Send(task.Receiver, task);
                        tasks.RemoveAt(0);
                    }
                    else if (tasks[0] is PingTask)
                    {
                        Ping();
                        tasks.RemoveAt(0);
                    }
                    else if (tasks[0] is AvaibleUserTask)
                    {
                        SendAvaibleUser(tasks[0] as AvaibleUserTask);
                        tasks.RemoveAt(0);
                    }
                    else
                    {
                        Console.WriteLine("Verarbeitungsfehler!");
                        tasks.RemoveAt(0);
                    }
                } while (tasks.Any() && stop == false);
    
    
                if (!tasks.Any() && onlineuser.Any() && stop == false)
                {
                    tasks.Add(new PingTask());
                }
            }
            public void Listen()
            {
                while(stop != true)
                {
                    
                    TcpClient received = null;
                    NetworkStream stream = null;
                    string contenttype = null;
                    BinaryFormatter formatter = new BinaryFormatter();
                  
                    listener.Start();
                  
                    try
                    {
                        received = listener.AcceptTcpClient();
    
                        if (received != null)
                        {
                            stream = received.GetStream();
                            contenttype = (string)formatter.Deserialize(stream);
                            if (contenttype != null)
                            {
                                if (contenttype == "RegisterTask")
                                {
                                    RegisterTask task = (RegisterTask)formatter.Deserialize(stream);
                                    tasks.Add(task);
                                }
                                else if (contenttype == "LoginTask")
                                {
                                    LoginTask task = (LoginTask)formatter.Deserialize(stream);
                                    tasks.Add(task);
                                }
                                else if (contenttype == "LogoutTask")
                                {
                                    LogoutTask task = (LogoutTask)formatter.Deserialize(stream);
                                    tasks.Add(task);
                                }
                                else if (contenttype == "MessageTask")
                                {
                                    MessageTask task = (MessageTask)formatter.Deserialize(stream);
                                    tasks.Add(task);
                                }
                                else if (contenttype == "AvaibleUserTask")
                                {
                                    AvaibleUserTask task = (AvaibleUserTask)formatter.Deserialize(stream);
                                    tasks.Add(task);
                                }
                                else
                                {
                                    throw new Exception();
                                }
                               
                            }
                        }
                    }
                    catch
                    {
                        
                    }
                    finally
                    {
                        listener.Stop();
                        received.Close();
                        stream.Close();
                    }
    
    
                }



    • Bearbeitet R3turnz Montag, 26. Oktober 2015 17:26
    Montag, 26. Oktober 2015 17:25

Antworten

  • Hallo,

    Ich finde, dass alles in diesem Beispiel  zu komplex gelöst ist. Der tt Thread ist überflüssig. Die Bearbeitung der Verbindung findet in gleichem Thread  mit Listener statt, also in dieser Zeit ist der Server für die weitere Clients nicht erreichbar.

    AccptTcpClnt t = new AccptTcpClnt(AccptClnt); 

    Eine Referenz (t) zu der Methode AccptClnt wird erzeugt.

    Thread tt = new Thread(() => t(ref handler, listener));
    tt.IsBackground = true;
    tt.Start();

    Ein Background Thread wird erzeugt und gestartet. Die Methode AccptClnt wird in diesem Thread ausgeführt.


    while (isRunning && tt.IsAlive && handler == null)      

    Thread.Sleep(500);

    Hier wird auf eine Verbindung (also einen Event von tt) gewartet.


    //Delegate für die Methode StartListening
    delegate void mThread(ref book isRunning);
    //Delegate für die Methode AccpClnt
    delegate void AccptTcpClnt(ref TcpClient client, TcpListener listener);
    


    Grüße



    Dienstag, 27. Oktober 2015 16:45
  • Hallo,

    Thread mit der Listen-Methode bleibt in listener.AcceptTcpClient() hängen. Es muss die Methode Stop() aufgerufen werden. 

    Du kannst die Klasse Function mit der neuen Methode StopListener erweitern:

    public void StopListener()
    {
       if(listener!=null)
       {
         listener.Stop();
         stop =true; 
       }
    
    }

    Dann in der Main-Methode die Methode StopListener() aufrufen.

                    if(cmd.ToLower() == "stop")
                    {
                        MainFunction.StopListener();
    
                    }
                    else
                    {
                        Console.WriteLine("Unbekannter Befehl.");
                    }

    Grüße

    • Als Antwort vorgeschlagen Iso7 Montag, 2. November 2015 10:26
    • Als Antwort markiert Aleksander Chalabashiev Freitag, 6. November 2015 08:39
    Montag, 26. Oktober 2015 22:09
  • Hallo,

    grundsätzlich führt jeder Vordergrund-Thread dazu, dass ein Programm nicht beendet wird. Weswegen man alle Threads, die nicht das Programmende verhindern sollen, mit IsBackground als Hintergrund-Thread anlegen sollte.

    Siehe dazu: Vordergrund- und Hintergrundthreads

    Konkreter für obigen Fall: Cancel blocking AcceptTcpClient call

    Gruß Elmar

    • Als Antwort vorgeschlagen Iso7 Montag, 2. November 2015 10:26
    • Als Antwort markiert Aleksander Chalabashiev Freitag, 6. November 2015 08:38
    Dienstag, 27. Oktober 2015 08:42
    Beantworter
  • Hallo,

    "Iso7" hat Recht. Entschuldige, ich habe bei dem Beispiel leider nur sehr flüchtig drauf geschaut und schon beim Auffinden von IsBackground mit dem Lesen aufgehört... Das ist eigentlich das Einzige, was Du Deinem Code zunächst hinzufügen solltest. Denn der Rest ist bestenfalls pseudo-intellektuelles Meta-Programming ;)

    P. S.: Zu Deinem zweiten Codebeispiel wäre zu sagen, dass der der Switch und Cast vor dem tasks.Add(task); sinnfrei ist.

    Den contentType könntest Du über einen BinaryWriter/Reader als Zeichenkette in den Stream schreiben/lesen, anstatt einen BinaryFormatter zu bemühen. Das ist effizienter und ein BinaryWriter/Reader würde weiteren Raum für Erweiterungen bieten (falls es mal dazu kommen sollte).

    Gruß Elmar

    Mittwoch, 28. Oktober 2015 08:44
    Beantworter

Alle Antworten

  • Hallo,

    Thread mit der Listen-Methode bleibt in listener.AcceptTcpClient() hängen. Es muss die Methode Stop() aufgerufen werden. 

    Du kannst die Klasse Function mit der neuen Methode StopListener erweitern:

    public void StopListener()
    {
       if(listener!=null)
       {
         listener.Stop();
         stop =true; 
       }
    
    }

    Dann in der Main-Methode die Methode StopListener() aufrufen.

                    if(cmd.ToLower() == "stop")
                    {
                        MainFunction.StopListener();
    
                    }
                    else
                    {
                        Console.WriteLine("Unbekannter Befehl.");
                    }

    Grüße

    • Als Antwort vorgeschlagen Iso7 Montag, 2. November 2015 10:26
    • Als Antwort markiert Aleksander Chalabashiev Freitag, 6. November 2015 08:39
    Montag, 26. Oktober 2015 22:09
  • Hallo,

    grundsätzlich führt jeder Vordergrund-Thread dazu, dass ein Programm nicht beendet wird. Weswegen man alle Threads, die nicht das Programmende verhindern sollen, mit IsBackground als Hintergrund-Thread anlegen sollte.

    Siehe dazu: Vordergrund- und Hintergrundthreads

    Konkreter für obigen Fall: Cancel blocking AcceptTcpClient call

    Gruß Elmar

    • Als Antwort vorgeschlagen Iso7 Montag, 2. November 2015 10:26
    • Als Antwort markiert Aleksander Chalabashiev Freitag, 6. November 2015 08:38
    Dienstag, 27. Oktober 2015 08:42
    Beantworter
  • Was genau will er mit diesem Code anstellen? (Cancel blocking accepttcpclient call)

    AccptTcpClnt t = new AccptTcpClnt(AccptClnt);
    
            Thread tt = new Thread(() => t(ref handler, listener));
            tt.IsBackground = true;
            tt.Start(); //the AcceptTcpClient() is a blocking method, so we are invoking it    in a seperate thread so that we can break the while loop wher isRunning becomes false
    
            while (isRunning && tt.IsAlive && handler == null) 
            Thread.Sleep(500); //change the time as you prefer

    Oder wie genau verwaltet er diese Delegaten:

    delegate void mThread(ref book isRunning);
    delegate void AccptTcpClnt(ref TcpClient client, TcpListener listener);

    Danke!

    Ps: Er verwendet einen  Lambda-Ausdruck etc, im Prinzip meine ich eine leserliche Schreibweise(für mich, klar das es für durchaus  leserlich sein kann )


    • Bearbeitet R3turnz Dienstag, 27. Oktober 2015 15:13
    Dienstag, 27. Oktober 2015 15:02
  • Hallo,

    Ich finde, dass alles in diesem Beispiel  zu komplex gelöst ist. Der tt Thread ist überflüssig. Die Bearbeitung der Verbindung findet in gleichem Thread  mit Listener statt, also in dieser Zeit ist der Server für die weitere Clients nicht erreichbar.

    AccptTcpClnt t = new AccptTcpClnt(AccptClnt); 

    Eine Referenz (t) zu der Methode AccptClnt wird erzeugt.

    Thread tt = new Thread(() => t(ref handler, listener));
    tt.IsBackground = true;
    tt.Start();

    Ein Background Thread wird erzeugt und gestartet. Die Methode AccptClnt wird in diesem Thread ausgeführt.


    while (isRunning && tt.IsAlive && handler == null)      

    Thread.Sleep(500);

    Hier wird auf eine Verbindung (also einen Event von tt) gewartet.


    //Delegate für die Methode StartListening
    delegate void mThread(ref book isRunning);
    //Delegate für die Methode AccpClnt
    delegate void AccptTcpClnt(ref TcpClient client, TcpListener listener);
    


    Grüße



    Dienstag, 27. Oktober 2015 16:45
  • Hallo,

    "Iso7" hat Recht. Entschuldige, ich habe bei dem Beispiel leider nur sehr flüchtig drauf geschaut und schon beim Auffinden von IsBackground mit dem Lesen aufgehört... Das ist eigentlich das Einzige, was Du Deinem Code zunächst hinzufügen solltest. Denn der Rest ist bestenfalls pseudo-intellektuelles Meta-Programming ;)

    P. S.: Zu Deinem zweiten Codebeispiel wäre zu sagen, dass der der Switch und Cast vor dem tasks.Add(task); sinnfrei ist.

    Den contentType könntest Du über einen BinaryWriter/Reader als Zeichenkette in den Stream schreiben/lesen, anstatt einen BinaryFormatter zu bemühen. Das ist effizienter und ein BinaryWriter/Reader würde weiteren Raum für Erweiterungen bieten (falls es mal dazu kommen sollte).

    Gruß Elmar

    Mittwoch, 28. Oktober 2015 08:44
    Beantworter