Laden...

Wie Thread der socket.Receive ausführt beenden?

Erstellt von Richter vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.500 Views
R
Richter Themenstarter:in
104 Beiträge seit 2006
vor 12 Jahren
Wie Thread der socket.Receive ausführt beenden?

Hallo!

Ich lausche in meinem Programm einer Art Börsentickerstream. In meinem Fenster starte ich in der button_click(..) die Funktion StartBitcoinchartsTicker(). Diese startet nun in einem neuen Thread die bitcoinchartlistener() funktion die nun in einer Endlosschleife den Stream abhört. Der Thread wird gespeichert als ThreadX

Wenn ich mein Programmfenster schließe und damit das Programm beenden will, dann "lebt" bitcoinchartslistener einfach weiter. Auch ein ThreadX.abort() bringt nichts. in der Receive funktion kommt dieser Befehl sich zu beenden wohl nicht zur ausführung.

Wie kann ich mein Programm vollständig beenden?

Ich habe folgenden Code:


static bool isBitcoinchartsTickerRunning = false; 
        public static System.Threading.Thread StartBitcoinchartsTicker()
        {
            if (isBitcoinchartsTickerRunning == false)
            {
                return run(() => { bitcoinchartlistener(); });
            }
            return null;
        }

        static BitCoinChartsData bitcoinchartlistener()
        {
            Socket sock = null;
            IPHostEntry hostEntry = null;

            hostEntry = Dns.GetHostEntry("bitcoincharts.com");

            // Nutze die Eigenschaft AddressFamily von IPEndPoint um Konflikte zwischen
            // IPv4 und IPv6zu vermeiden. Gehe dazu die Adressliste mit einer Schleife durch.
            foreach (IPAddress address in hostEntry.AddressList)
            {
                IPEndPoint ipo = new IPEndPoint(address, 27007);
                Socket tempSocket = new Socket(ipo.AddressFamily,
                                               SocketType.Stream,
                                               ProtocolType.Tcp);

                tempSocket.Connect(ipo);

                if (tempSocket.Connected)
                {
                    sock = tempSocket;
                    break;
                }
                else
                {
                    continue;
                }
            }


            Byte[] bytesReceived = new Byte[94096];

            // Instanziere ein gültiges Socket Objekt mit den übergebenen Argumenten

            if (sock == null)
            {
                if (OnError != null)
                {OnError("Could not connect to Bitcoinchart-Datastream");}
            }

            isBitcoinchartsTickerRunning=true;

            int bytes = 0;
            // Empfange die Daten und konvertiere sie
            do
            {
                bytes = sock.Receive(bytesReceived, bytesReceived.Length, SocketFlags.None);

                // kovertiere die Byte Daten in einen string
                //page = page + Encoding.ASCII.GetString(bytesReceived, 0, bytes);
                if(OnNewBitcoinchartData!=null)
                {
                    string JSON = Encoding.ASCII.GetString(bytesReceived, 0, bytes);
                    string[] JSONs = JSON.Split(new string[]{"\0"},StringSplitOptions.RemoveEmptyEntries);
                    foreach(string JS in JSONs)
                    {
                        JS.Replace("\0","");
                        OnNewBitcoinchartData(new BitCoinChartsData(JS));
                    }
                }
            } while (bytes > 0);

            // Unterbinde alle weiteren Send() und Receive() Aktivitäten am Socket
            sock.Shutdown(SocketShutdown.Both);
            sock.Close();
            if (OnError != null)
            { OnError("Could not connect to Bitcoinchart-Datastream"); }
            isBitcoinchartsTickerRunning = false;
            return null;
        }

Nevu - Intelligente Maschinen, die Zukunft alles rund um das Thema Künstliche Intelligenz!

R
Richter Themenstarter:in
104 Beiträge seit 2006
vor 12 Jahren

Ich habe eine (in meinen Augen nicht elegante) Lösung gefunden:

ich platziere ein

                while(sock.Available == 0)
                {
                    System.Threading.Thread.Sleep(100);
                }

vor das Recive.

Bitte dennoch um Ideen wie man es besser machen könnte 😃

Nevu - Intelligente Maschinen, die Zukunft alles rund um das Thema Künstliche Intelligenz!

B
387 Beiträge seit 2005
vor 12 Jahren

Hi,

ein paar Vorschläge:*Socket.Receive müsste eine Überladung haben, in der man einen Timeout angeben kann...? So kannst du zum Beispiel immer nach einer bestimmten Zeit prüfen, ob der Thread abgebrochen werden soll *Bei dem Thread das Background-Flag auf true setzen, dann wird er automatisch Beendet, wenn du deine Anwendung schließt *Thread.Abort nicht verwenden, sofern dus wirklich nicht anders hin bekommst

Gruß
Roland

U
1.688 Beiträge seit 2007
vor 12 Jahren

Hallo,

weitere Vorschläge:

  • beim Beenden den Socket schließen (und die entsprechende Exception fangen)
  • asynchrone Funktionen benutzen (BeginReceive, ...)
W
872 Beiträge seit 2005
vor 12 Jahren

Du musst auf den Socket die Socket.ReceiveTimeout Property auf einen Wert setzen, so dass ein Timeout eine Socket-Exception auslöst.
Ansonsten solltest Du entweder einen Task verwenden oder einen echten Thread starten und die vorher beschriebene BackGround Property setzen.