Thread mit socket.receive lastet CPU zu 99% aus

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von nopi.

    Thread mit socket.receive lastet CPU zu 99% aus

    Hallo zusammen,

    ich habe nach vielen Nächten miitlerweile scheinbar nur noch Leere an der Stelle wo sonst Hirn sitzen sollte und finde für mein Problem keine Lösung.

    Ich starte einen Thread, in dem eine Socketverbindung aufgebaut wird. Anschließend wartet der Thread mit einem Loop auf neu empfangene Daten aus der Verbindung. Dabei geht die CPU uslastung auf 99% hoch, wobei das wohl aus dem Loop kommen muss. Jetzt gibt es aber tausende Programme die an einer Socketverbindung auf einen Empfang warten und die CPU Auslastung dabei nicht ans Limit treiben. Also mache ich etwas falsch, aber was?

    Mein Code sieht wie folgt aus:

    VB.NET-Quellcode

    1. Do Until Beenden
    2. Try
    3. 'Prüfen ob Verbindung connected und Daten voranden
    4. If (Socket.Connected And Socket.Available > 0) Then
    5. Dim Receive(1024) As Byte
    6. Dim BytesFromServer As Int32
    7. BytesFromServer = Socket.Receive(Receive)
    8. Receive_String = (Encoding.ASCII.GetString(Receive, 0, BytesFromServer))
    9. 'Empfangene Daten in Logfile schreiben
    10. LogfileEintragText = Receive_String
    11. LogfileEintrag()
    12. End If
    13. 'Fehlerbehandlung, wenn Socket-Verbindung ein Problem feststellt wird hier abgebrochen
    14. Catch e As SocketException
    15. Catch e As Exception
    16. End Try
    17. Loop


    Für mich lautet nun die Frage des Tages: "Wie bekomme ich einen permanenten Socket.receive hin, ohne das die CPU Auslastung explodiert?"

    Danke vorab...

    nopi
    Vielleicht solltest Du in der Loop eine angemessene Pause warten

    VB.NET-Quellcode

    1. System.Threadding.Thread.Sleep(100) ' oder so
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Mit dem warten komme ich jetzt wieder ins schwitzen. Meine übliche Angst: "Könnte ich vielleicht etwas verpassen?"

    Der Kommunikationspartner am anderen Ende kann im Abstand von ca. 20-40ms neue Telegramme schicken. Wenn ich jetzt warte, was passiert dann, wenn in dieser Zeit der Partner zwei Telegramme lostritt?

    Wie macht ein Netzwerksniffer so was? Der wartet ja auch nicht beim Empfang sondern bekommt alles mit was auf der Leitung passiert.

    Habt ihr noch eine Idee?
    mit Polling ungefähr so:

    VB.NET-Quellcode

    1. Private client As TcpClient
    2. Private stream As NetworkStream
    3. Sub New()
    4. client = New TcpClient(server, port)
    5. stream = client.GetStream()
    6. End Sub
    7. Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    8. If (Not stream.DataAvailable) Then
    9. Return
    10. End If
    11. ' Receive the TcpServer.response.
    12. ' Buffer to store the response bytes.
    13. Dim data As Byte() = New Byte(256) {}
    14. ' String to store the response ASCII representation.
    15. Dim responseData As String = String.Empty
    16. ' Read the first batch of the TcpServer response bytes.
    17. Dim bytes As Int32 = stream.Read(data, 0, data.Length)
    18. responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
    19. tbReceived.Text += responseData
    20. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Erst einmal Danke für die Tips!!

    Ich habe gestern die Idee von RodFromGermany ausprobiert. Soweit scheint es zu funktionieren. Mit dem Polling sinkt die CPU Auslastung auf max 1% und scheinbar verliere ich dabei auch keine Daten. Das ist prima und genau das was ich gesucht habe.
    Aber .... jede Problemlösung stellt einen vor eine neue Aufgabe :S

    Ich habe in Wirklichkeit zwei Threads, die bei an jeweils unterschiedlichen Verbindungen darauf warten sollen das Daten empfangen werden. Ich habe mir daher gedacht "sei schlau" und mach dir einfach zwei Timer. Einen für den ersten Thread und einen für den zweiten. Aber das funktioniert nicht. Wenn ich beide Timer aktiviert habe, dann scheint es als würde keiner der beiden Threads mehr aufgerufen. Deaktiviere ich einen der beiden Timer funktioniert das ganze mit dem verbleibenden Timer einwandfrei.

    Und noch ein Problem trat auf. Ich habe versucht einen Timer erst nach dem erfolgten Verbindungsaufbau mit Timer1.enabled =true zu starten. Aber das geht nicht. Der Timer startet nicht. Oder startet er vielleicht doch, nur kann ich ihn nicht ohne weiteres verwenden?

    Ich hoffe sehr, ihr rettet mich vor weiteren schlaflosen Nächten......
    Nimm nur einen Timer und ruf auf:

    VB.NET-Quellcode

    1. Sub Timer_Tick()
    2. Polle_Thread1()
    3. Polle_Thread2()
    4. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!