![]() |
Thread.Queue, Zeitmessung, Thread hängt angeblich
Hallo zusammen,
ich habe versucht den Titel auf das nötigste zu reduzieren. Folgender Fall: Ich habe ganz viele Threads, welche früher über Synchronize jeweile eine eigene "zeitaufwändige" Funktion aufgerufen haben. Ich wollte, das die VCL nicht mehr hängt, auf Queue umstellen und habe vor und nach dem Synchronize eine Zeitmessung eingebaut
Delphi-Quellcode:
TC2 ist teilweise 500ms.
TC := GetTickCount;
//Synchronize(MeineFunktion); Queue(Nil, MeineFunktion); TC2 := GetTickCount - TC; //Protokollierung von TC2... Unter Synchronize verstehe ich das ja, aber wieso bei Queue auch? Hat jemand dazu eine Idee? Kann der Thread durch irgendwas "blockiert" sein und wenn ja, wie bekomme ich raus, durch was? Ich hoffe, ihr habt dazu eine Idee |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Zitat:
Kann es denn passieren, dass die gesamte Funktion inkl Zeitmessung auch mal vom Hauptthread direkt ausgeführt wird? In dem Fall entspricht das Queue nämlich einem Synchronize und du könntest stattdessen ForceQueue verwenden. |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Nein, der Source oben ist im Execute-Teil des Threads.
Was komisch ist, innerhalb der Funktion "MeineFunktion" habe ich auch eine Zeitmessung, die aber nicht zuschlägt. Das verstehe ich noch nicht wirklich... |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Just use a profiler and it will log the blocking method/function/operation, then track the call stack to get better understand how landed here and what it is waiting for.
I think any profiler will do, for my self and as daily driver i use NQS Method Timer from ![]() In other words wear investigator hat and think outside the box, you did not mention essential stuff like: 1) if the CPU is being used at that moment or not, like a core at full cycle rotating or not 2) Use Process Explorer or Process Hacker and watch the threads tab, what is going there, do you have rouge thread(s) triggering cosmic number of context switches or not 3) Is the UI responsive or not, can you increase the effect to longer period like 10 seconds and see if Windows mark the UI as non responsive, 4) Also important question, do you use Applicatio.ProcessMessages ? 5) Is there silent exceptions 6) What did you described might have similarity when a loop namely While..do or repeat until lost its bound and went full 32bit, but this can be easy to catch with high CPU usage. .... And good luck ! |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Zitat:
Führen code im Hauptthread aus. In windows: Synchronize udn Queue führen den code "sofort" im Hauptthread aus. ForceQueue setzt die Ausführung des Codes ans Ande der MessageQueue und führt den Code aus kurz bevor Application.OnIdle passiert. Ich habe außerdem festgestellt, dass Application.processmessages nicht gut mit Multithreading und Synchronization und warten und blockieren USW. zusammenspielt... also am Besten nie Application.processmessages nutzen. Am besten immer GetTickCount64 benutzen GitTickCount ist deprecated. Bei so kleinen workloads (null workload) vieleicht sogar nen ![]() |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Liste der Anhänge anzeigen (Anzahl: 2)
Hi Kas Ob.,
ich werde mir den Profiler angucken, danke für den Tip. Zu deinen Fragen: 1) Die CPU Auslastung ist die gesamte Zeit <2%. Auch zu dem Zeitpunkt, wo das Problem auftritt. 2) Im Prozess Explorer sieht man zum Zeitpunkt des Problems, dass einige Threads rot markiert werden. Ich denke, dass bedeutet, dass diese Threads hängen. Im Anhang auch 2 Bilder. Einmal vom VCL Thread und einmal von der Anwendung selber (ja es sind verdammt viele Threads, es ist auch eine große Anwendung) 3) Die Oberfläche des Programmes lässt sich wirklich nicht bedienen für ca 4-5s. Das Problem kann ich reproduzieren in meiner Anwendung allerdings dauert es nie länger als 5s. 4) Ich benutze Application.ProcessMessages nicht 5) Es gibt einige Stellen im Programm, wo Exceptions abgefangen und behandelt werden 6) CPU Auslastung ist keine vorhanden Für mich sieht es so aus, dass die besagten Threads in dem Moment keine Rechenzeit erhalten. Eine CPU Auslastung kann ich aber nicht feststellen.
Delphi-Quellcode:
So sieht das ganze grob aus.
while not Terminated do
begin //hier erfolgt eine Signalisierung über WaitForSingleObject und bei Timeout (=250ms), erfolgt der zyklische Aufruf unten if WaitForsingleObject(Irgendwas, 250, xxxx) = WAIT_OBJECT_0 do begin end; //zyklischer Aufruf TC := GetTickCount; //Synchronize(MeineFunktion); Queue(Nil, MeineFunktion); TC2 := GetTickCount - TC; //Protokollierung von TC2... end; Die Funktion "MeineFunktion" sieht etwa so aus:
Delphi-Quellcode:
Verwundert bin ich nur, dass die Protokollierung von TC2 zuschlägt, allerdings von TC4 nicht. (zur Info, die Protokollierung erfolgt nur, wenn der Wert >200ms ist)
procedure MeineFunktion;
begin var TC3 : DWORD; var TC4 : DWORD; TC3 := GetTickCount; //Mache irgendwas zeitaufwändiges TC4 := GetTickCount - TC3; //Protokollierung von TC4... end; |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
auch mit ForceQueue, erfolgt die Protokollierung von TC2 aber innerhalb der Funktion, schlägt keine Protokollierung von TC4 zu. VCL hängt auch.
Delphi-Quellcode:
while not Terminated do
begin //hier erfolgt eine Signalisierung über WaitForSingleObject und bei Timeout (=250ms), erfolgt der zyklische Aufruf unten if WaitForsingleObject(Irgendwas, 250, xxxx) = WAIT_OBJECT_0 do begin end; //zyklischer Aufruf TC := GetTickCount; //Synchronize(MeineFunktion); ForceQueue(Nil, MeineFunktion); TC2 := GetTickCount - TC; //Protokollierung von TC2... end; |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
Wo findet das "Protokolieren " statt?
Ist das eine Festplatte? oder eine andere Sequenzielle Systemresource? Vielleicht ein Bereich der durch einen Monitor, eine CS oder eine Mutex geschützt ist? Du musst die Sachen die im Nebenthread passieren woanders protokolieren als die Sachen die im Hauptthread passieren, wenn das Protokoll die Nebenläufigkeit nicht behindern soll. Das ist dir klar oder? Wenn du Nebenläufigkeit haben willst dürfen keine gemeinsamen Variablen oder Resourcen(Festplatte, Systembus, Schnittstelle, Systemhandle) genutzt werden. Es sei denn es ist dir egal wenn alle Threads die diese Resource benutzen jeweils warten bis sie benutztbar ist. |
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
|
AW: Thread.Queue, Zeitmessung, Thread hängt angeblich
TL;DR; ?
Ich habe auch schon TStopwatch probiert. Kommt zum gleichen Ergebnis wie GetTickCount. Zum Thema Protokollierung: Die sieht etwa so aus:
Delphi-Quellcode:
Die Protokollierung ist sicherlich nicht das Problem. Die Funktion wird sowohl für die Protokollierung von TC2 als auch TC4 benutzt, natürlich immer mit dem entsprechenden Übergabewert als Value und Aufrufer-String
procedure MyProto(aValue: DWord; aAufrufer : String);
begin if aValue >= 200 then //=200ms begin tmpStr := aAufrufer + ' - Value: ' + aValue.ToString; //Senden des Strings an den Protokoll-Thread, welcher für das Schreiben zuständig ist //PostThreadMessage zum Protokoll-Thread end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:49 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