![]() |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Zitat:
If you are using OnUDPRead and it is running in background thread context then what this loop suppose to serve ?
Delphi-Quellcode:
Where is running ? and it is hugging something and should be removed, yes altogether, remove it.
while not Terminated do
begin //here a signal is sent via WaitForSingleObject and if the timeout occurs (=250ms), the cyclic call below is made if WaitForsingleObject(Something, 250, xxxx) = WAIT_OBJECT_0 do begin end ; end ; Just take a step back and look at the big picture and simplify the whole thing, and don't answer my question, and trying to explain to me, and yes, imagine you are trying to explain the whole thing and i am %100 sure you will figure the miss use of over engineering you are doing. here a simple approach : OnUDPRead fired, we read, we are in background thread so no synchronization call of any sort is needed, we process and we exit, no looping no waiting for msg or anything inside these events. you need to log something then use a faster approach and don't want on disk or UI updates, use PostMessage and that is it. |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Ich versuche es nochmal zu erklären.
Threadübersicht: UDPServer Anzahl 1 = Thread Nummer 1 UDPClient Anzahl 1..35 = Thread Nummer 2..36 Verarbeitungsthread Anzahl 1..35 = Thread Nummer 37..71 weitere Threads, die für andere Funktionen zuständig sind, allerdings den Verarbeitungsthreads 37..71 auch Nachrichten schicken können. UDPServer gibt die empfangenen Daten an den UDPClient weiter, via PostThreadMessage UDPClient gibt Daten nach Prüfung und Validierung und anderen Dingen, an den Verarbeitungsthread weiter, via PostThreadMessage Verabreitungsthread sieht ungefähr so aus:
Delphi-Quellcode:
Wie gesagt, nur ein grober Auszug...
while not Terminated do
begin Return := MsgWaitForMultipleObjects (Handles, HandleBuffer, False, 251, QS_ALLINPUT); //case Return do //WAIT_OBJECT_0 //WAIT_OBJECT_0+Handles // : begin // while PeekMessage(MessageData, 0, 0, 0, PM_REMOVE) do // begin // Mach irgendwas mit der Nachricht... // end; // end; //WAIT_TIMEOUT //end; //zyklischer Aufruf var sw := TStopwatch.StartNew; var TC : DWORD; var TC2 : DWORD; TC := GetTickCount; //Synchronize(MeineFunktion); //Queue(Nil, MeineFunktion); //ForceQueue(Nil, MeineFunktion); t1 := sw.ElapsedMilliseconds; //Protokollierung von t1 ... TC2 := GetTickCount - TC; //Protokollierung von TC2 ... end ; |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Das Verhalten mit dem VCL Hänger scheint genau dann aufzutreten, wenn ich gleichzeitig die Verbindung zu allen 35 UDP Teilnehmern trenne (Netzwerkkabel ziehen oder ähnliches).
UDPClient Anzahl 1..35 = Thread Nummer 2..36 Die Telegramme zu den Clients werden softwareseitig quittiert (da UDP keine Standardmäßige Quittierung hat, ich weiß) und wenn nach einer Zeit X, keine Antwort kommt, wird der Client (=Thread) beendet mit ".Terminate". Wird das ganze bewusst nur für einen Client (= einen Thread) gemacht mit ".Terminate", passiert an der VCL nichts. Wird das ganze für 35 gleichzeitig gemacht, dann hängt es. Soviel habe ich schon rausbekommen |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Zitat:
This raise few questions why to mention UDPClient here ? what are their proposes on server side ? if you are responding then use SendTo from the server Binding/Handler to get better idea refer to this example ![]() May be your server doesn't use UDPCLient and this miss understanding on me (translation or something) we get to different problematic approach THE loop here how to do loop and handle thread messages ![]() ![]() Read the question and answers on SO also all the comments there, specially this one Zitat:
|
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Zitat:
Verarbeitungsthread Anzahl 1..35 = Thread Nummer 37..71 Either group causing the main thread to block in waiting state, this behaviour red color on CPU usage unless you are not performing IO operations (reading/writing to disk or network in tight loop) then means one thing, high thread contention and main thread is not couping with it jumping from one place to another and have no time to process Messages. Capture the culprit, try to exit either group before performing this sudden close, see what is wrong and change that timeout at 250ms to something useful like 30seconds (30000ms), you are not expecting messages that much after all. Can you disconnect all the clients at once form server ? what happen ? etc... |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Zitat:
Verstehe das Problem nicht. Ich rufe doch PeekMessage in einer While Schleife auf, so wie in dem verlinkten Beitrag. Zitat:
Ich trenne die UDPClients gleichzeitig! und genau dann tritt das Problem auf. Trenne ich nur EINEN Client, passiert das Problem NICHT. |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Zitat:
Are they TThread ? and more important question Are you using a UDPClient or TIdUDPClient on server part ? And more importanter then grammar is When you say 250ms is needed ....... WHYYYYYY What are those thread suppose to do ? Send and/or receive or processing too ? are you piling jobs on threads and for that you need them to wait for 250ms then do another thing ? that is wrong and contradict the point of using threads to begin with. When you say you have threads to received on the that event then that event is the one coming form dedicated thread allocated by Indy library to handle you recv and send, then use UDP server to send, and in that event just recv/read and utilize its parameter in that even to send when finished, this can be from any other threads (literally from anywhere). explain in plain text the logic from receiving a packet to send it, do it on paper and you will find the root of these hugs. Again refer to ![]()
Delphi-Quellcode:
Do send using "ABinding: TIdSocketHandle" "ABinding.SendTo" from anywhere, in other words no dedicated thread, to duck rubber explain it,
procedure TUDPMainForm.UDPServerUDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var DataStringStream: TStringStream; s: String; begin DataStringStream := TStringStream.Create(''); try DataStringStream.CopyFrom(AData, AData.Size); UDPMemo.Lines.Add('Received "' + DataStringStream.DataString + '" from ' + ABinding.PeerIP + ' on port ' + IntToStr(ABinding.PeerPort)); s := 'Replied from ' + UDPServer.LocalName + ' to "' + DataStringStream.DataString + '"'; ABinding.SendTo(ABinding.PeerIP, ABinding.PeerPort, s[1], Length(s)); finally DataStringStream.Free; end; end; having TIdUDPServer on your application/server will remove the need for threads to receive and send, leaving one group of threads, the processing, you want to dedicate one per client ? ok that is fine, now i want you to question the existence of two group of threads, and explain them. I am sure you miss understanding one functionality somewhere. |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Receiving from UDP is or can be blocking and can be non blocking, you really don't need to dedicate a thread per identified connection, just recv/read and pass to a thread then write/send from anywhere.
simplify the the groups need and keep only one, also if you like loop like that then wait on call and block on recv then handle then send, loop again, this will even simplify the things further, removing the need to pass data between threads altogether. |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
One more thing to understand, that you might be missing,
UDP is unlike TCP, in case of TCP you can not send without checking the socket is ready to write/send, well you can but it might fail with error and ask you to block or to wait, UDP it is ready always, like always always, just SendTo and call it a day, it might fail or drop the packet but you don't have control about it as there is nothing to do about it, will not explain how to mitigate this here as it is irrelevant your case, 35 clients unless the traffic is saturating you connection it will work like charm. |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Ich versuche auf einige Fragen zu antworten aber das Senden mit UDP hin und her mit softwareseitiger Quittierung funktioniert ja. OHNE VCL Hänger.
Der UDPServer ist ein Thread und empfängt die Daten. Für jeden UDP Teilnehmer im Netzwerk (=Client), erzeuge ich mir im Server einen eigenen Thread, der dann das Senden an den Client übernimmt (dieser heißt bei mir Client-Thread und ist natürlich ein TThread). Das Senden macht NICHT der Server-Thread direkt. Der Server gibt dem Client-Thread nur die Hostadresse und Port (vom Empfang) mit. Im Client-Thread wird ein IdUDPClient erstellt, welcher das Senden übernimmt an Host und Port. Der Client-Thread überwacht auch selber die Quittierung der UDP Telegramme. Daher braucht sich die Server-Komponente NUR um den Empfang kümmern. Der Datenaustausch mit dem Client-Endgerät, wird durch einen Client-Thread gemacht. Der Client-Thread überwacht seine MessageQueue mit besagter PeekMessage-Technik und wenn für eine gewisse Zeit, keine Daten mehr eintreffen, wird der Teilnehmer als offline erkannt und der Client-Thread terminiert sich mit ".Terminate" |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:12 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz