Backgroundworker kann durch Socket nicht beendet werden



  • Hallo

    Da das Ganze ja dauerhaft laufen soll habe ich folgenden Code nun innerhalb einer while(true) Schleife im BGW laufen lassen.

    // Hier der asynchrone Aufruf 
                    serverSocket.BeginAccept(new AsyncCallback(OnAccept), null);
    

    Ausführen kann ich den code. Aber die OnAccept Methode wird nur ein einziges mal beim starten aufgerufen. Danach nicht mehr. Auch wenn der Client weiterhin Daten sendet.

    Gruß



  • BeginAccept() dient dazu die Verbindung des Clients zu akzeptieren, mehr nicht. Um Daten vom Client empfangen zu können, benötigst du Begin-/EndReceive() (siehe mein Beispiel oben). Wenn du dich für asynchrone Aufrufe entscheidest, dann ist der BackgroundWorker überflüssig, das ist ja gerade der Vorteil.

    • Willst du an deinem bestehenden Code nicht viel Ändern, dann bleib beim BGW, setzt das Accept() in eine Schleife und führ das Receive solange aus, bis vom Client alle Daten abgeholt wurden
    • Willst du asynchron arbeiten, kann der BGW weg und du musst wie in meinem Beispiel vorgehen. (Einfach mal nach googlen)


  • Hi

    Ja, soweit (eigentlich) so klar. Ich war eben etwas voreilig mit Copy/Paste.

    Prinzipiell möchte ich gerne die Asynchrone Variante verwenden. Jedoch soll das gnaze nicht beim starten der Applikation angetriggert werden, sondern ich möchte mit einem Start und Stop Button das empfangen starten und stoppen.

    Wäre es daher sinnvoll die Verbindung wie in deinem Beispiel zu akzeptieren und dann in einem BGW die Daten zu empfangen?

    Gruß



  • Nein wäre es nicht. BeginXXX/EndXXX bringen ja den Vorteil, das das UI davon unbehelligt bleibt, da diese Methoden im Threadpool einen eigenen Thread anlegen. Um dem UI Änderungen zu vermitteln, musst du dann Dispatcher.Invoke() aufrufen.

    Du kannst den Code aus der Form_Loaded-Methode auch einfach in die Click-Methode des Start-Buttons einbauen.



  • Hallo

    U.a. habe ich mir mal folgenden Link angeschaut:
    http://msdn.microsoft.com/de-de/library/bbx2eya8(v=vs.80).aspx

    Ich glaube (hoffe) das Ganze so langsam zu verstehen. Benutze ich BeginnXXX/EndXXX wird der Callback in einem extra Thread bearbeitet. Benutze ich den BGW wäre das Doppelt gemoppelt.
    Morgen werde ich das ganze nochmals programmiertechnisch umzusetzen.
    Bei meiner Recherche bin ich auch auf folgenden Link gestoßen: http://www.codeplanet.eu/tutorials/csharp/4-tcp-ip-socket-programmierung-in-csharp.html?start=2
    Ist es zu empfehlen TcpClient und TcpListener zu verwenden?



  • Hallo

    Also ein Stück bin ich nun weiter.
    Ich habe mal folgendes versucht umzusetzen. Das ist ähnlich wie mir vorher geraten wurde. Prinzipiell funktionierts auch, jedoch wird durch die while(true) schleife meine Form blockiert.

    Wie kann ich das denn umgehen bzw verhindern?

    Anbei mal der Code:

    private void button1_Click(object sender, EventArgs e)
            {
                    StateObject myFinalStateobject  = new StateObject();
                    IPEndPoint ipEndPoint           = new IPEndPoint(IPAddress.Any  , myPort);
                    Socket mySocket                 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    StartListening(ipEndPoint);
    
            }
    
            public void StartListening(IPEndPoint localEP)
            {
                Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
                    listener.Bind(localEP);
                    listener.Listen(10);
    // Diese Schleife macht das Problem
                    while (true)
                    {
                        allDone.Reset();
                        listener.BeginAccept(new AsyncCallback(acceptCallback), listener);
                        if (allDone.WaitOne(2000)) { SetTextRecieveLog("Verbindung Erfolgreich aufgebaut! "); }
                        else { SetTextRecieveLog("Timeout Verbindungsaufbau" + localEP.ToString()); }
                    }
            }
    
            public void acceptCallback(IAsyncResult ar)
            {
                allDone.Set();
                Socket listener = (Socket)ar.AsyncState;
                Socket handler = listener.EndAccept(ar);
                // Additional code to read data goes here.  
                // Create the state object.
                StateObject state = new StateObject();
                state.workSocket = handler;
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
            }
    


  • Nun auch als Mitglied......



  • Mach die Schleife weg und ruf in acceptCallback() nochmals BeginAccept() auf. So erzeugst du wiederholtest die Abfrage von Client-Verbindungen.



  • Hi

    Mach die Schleife weg und ruf in acceptCallback() nochmals BeginAccept() auf. So erzeugst du wiederholtest die Abfrage von Client-Verbindungen.

    Die Lösung funktioniert leider nicht.

    Mitlerweile habe ich es hinbekommen.
    Den Socket habe ich doch schon. Daher muss ich doch irgendwie fortlaufend die BeginnReceive Methode aufrufen-

    Jedoch finde ich das das nicht so ne ganz saubere Lösung ist da meine Lösung eher Zeitgesteurt und nicht Ereignisgesteuert ist.

    Irgendwie muss es doch möglich sein die BeginnReceive Methode aufzurufen, direkt nach dem Daten empfangen wurden??? Ich habs schon mit

    receiveDone.WaitOne
    

    () versucht, aber das hat auch nicht funktioniert....

    Hier mal die zeitgesteuerte Lösung:

    public void acceptCallback(IAsyncResult ar)
            {
                allDone.Set();
                Socket listener = (Socket)ar.AsyncState;
                Socket handler = listener.EndAccept(ar);
    
                // Additional code to read data goes here.  
                // Create the state object.
                listener.BeginAccept(new AsyncCallback(acceptCallback), listener);
                StateObject state = new StateObject();
                state.workSocket = handler;
                while (true)
                {
                    receiveDone.Reset();
                    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
    
                    Thread.Sleep(1000);
                    if (myState.sb.ToString() != "") SetTextRecieveLog(myState.sb.ToString());
                    myState.sb.Clear();
                }
    
            }
    


  • Hi

    Da ich noch immer nicht so richtig weiter komme möchte ich meine Frage mal etwas konkreter stellen:

    Folgender Code:

    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(readCallback), state);
    

    Wenn ich das richtig verstanden habe wird doch readCallback nur aufgerufen nachdem wirklich Daten vom Client empfangen wurden? Oder nicht?

    Bei mir wird diese Funktion ständig aufgerufen wenn ich ein schleife um BeginRecieve mache...


Anmelden zum Antworten