AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Ursache für hängende Applikation herausfinden
Thema durchsuchen
Ansicht
Themen-Optionen

Ursache für hängende Applikation herausfinden

Ein Thema von Bodenseematze · begonnen am 29. Jan 2024 · letzter Beitrag vom 27. Feb 2024
Antwort Antwort
Seite 3 von 4     123 4      
Bodenseematze

Registriert seit: 10. Jul 2023
68 Beiträge
 
#21

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 12:33
Hmm, auch wenn ich die Stelle Application.ProcessMessages() im Code mit Sleep(0) oder Windows.Yield() austausche,
bleibt das ganze (wie gewohnt ) hängen...

Daran kann es also nicht (nur) liegen...
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
353 Beiträge
 
#22

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 12:39
Hi,

First and foremost never ever ever ever use Application.ProcessMessages(); in background thread and anywhere in general !, nothing good will come from it, and will add more failure scenarios that no one can imagine or think of.

Now to this whole big thread, it is way more complex than it should be.

My suggestion for your case (the code above) to drop it all and replace it with something like the a thread that have one event (not two), single one will do the job perfectly, or even remove the event altogether and use simple Sleep or SleepEx with very short sleep time (interval) like 50ms (1/20 of second), check triggering condition and perform one of the following
1) Enabled / Disabled nothing need to be done, loop again.
2) Exit request, then exit.
3) Need to call or notify the main thread then use PostMessage (simple like that) and loop again.
4) You want more control over timing and intervals then use Sleep(1).
5) Access the conditions from the threads itself only using.

From the code i deduce you are using this only for Windows then hide this new small thread in small TWinControl (or an invisible form) or what ever you see fit, and implement the a Message handler for that Message coming form PostMessage, and that is it.

On side note : PostMessage will of course use a window message, and most importantly if for some reason the message queue is full or blocked (the messages are not being process for other defect or bugs) then Synchronize from a thread will not be helpful too and will only make finding the real bug/flaw harder, Synchronize will only waste your time finding the bug in almost every scenario were things went wrong.
Also if PostMessage doesn't work or fail then Synchronize will not help either.
Kas
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
353 Beiträge
 
#23

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 12:46
Hmm, auch wenn ich die Stelle Application.ProcessMessages() im Code mit Sleep(0) oder Windows.Yield() austausche,
bleibt das ganze (wie gewohnt ) hängen...

Daran kann es also nicht (nur) liegen...
Remove Synchronize, redesign it without Synchronize.
Kas
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.592 Beiträge
 
Delphi 11 Alexandria
 
#24

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 13:01
Der Aufruf passierte laut Stacktrace 67 Zeilen weiter unten ab dem begin des Execute gezählt. Da ist im geposteten Quelltext ein end. Da müsstest du noch einmal schauen, was dort vorher stand.

Und wenn nun ohne ProcessMessages die Anwendung hängt... sieht der Bugreport noch genauso aus? Dein Timer nutzt ja nicht immer Synchronize. Kann es vorkommen, dass es ohne aufgrufen wird und dort etwas mit der VCL passiert?

Da es viele Aktionen abzuarbeiten gibt und das etwas länger dauert, verwende ich eine Mini-Form soz. als "Bitte Warten..."-Anzeige.
In dieser wird ein Anzeigetext gesetzt (ändert sich mit der aktuellen Aktion) und mit zu und abnehmenden "..." wird signalisiert, dass die Arbeit noch am Laufen ist.
Für dieses Zu- und Abnehmen habe ich eine eigene Klasse TTimerThread verwendet, die einen Thread basierten Timer zur Verfügung stellt bzw. stellen soll.
Wenn du im Hauptthread eine Aktion ausführst, kann auch ein Thread keine Aktualisierung der GUI durchführen. Dann bleibt Synchronize schlicht hängen, weil Synchronize voraussetzt, dass der Hauptthread auch funktionsfähig ist, sprich Nachrichten abarbeitet. Das Synchronize wird in WM_IDLE abgearbeitet. Wenn der Hauptthread beschäfitgt ist, passiert das nicht.

Nicht die Statusanzeige oder deren Steuerung gehören in den Thread sondern die lange dauernden Aktionen selbst.

Alternativ (aber nicht so schön) könntest du auch ein threadbasiertes Fenster anzeigen. Das kann auch direkt aus dem Thread ohne Synchonisierung verwendet werden. Ich habe dafür mal eine kleine Bibliothek angefangen:
https://github.com/jaenicke/MTCL
Da es dafür mittlerweile doch Interesse gibt, arbeite ich daran vielleicht doch mal weiter...
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.084 Beiträge
 
Delphi 12 Athens
 
#25

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 13:34
Wenn in Application.ProcessMessages wirklich nur die MessageList direkt verarbeitet würde,
dann wäre es egal, die der Thread vermutlich eh nichts in "seiner" Queue hat (bzw. noch keine Queue erstellt war)

Aber dort gibt es eben auch noch anderen Code, welcher auf globale Objekte/Variablen zugreift, welche halt nicht thread-safe sind.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
702 Beiträge
 
Delphi 12 Athens
 
#26

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 13:54
Hmm, auch wenn ich die Stelle Application.ProcessMessages() im Code mit Sleep(0) oder Windows.Yield() austausche,
bleibt das ganze (wie gewohnt ) hängen...

Daran kann es also nicht (nur) liegen...
Nur noch was am Rande: MsgWait.. macht innerhalb eines sekundären Threads keinen Sinn da ein solcher Thread keine message queue hat! Er wird also niemals eine input-message (QS_ALLINPUT) bekommen, alle vom Benutzer generierten Messages (mouse, keyboard) landen in der Queue des main threads und der sekundäre thread sieht sie nicht.
Peter Below
  Mit Zitat antworten Zitat
Bodenseematze

Registriert seit: 10. Jul 2023
68 Beiträge
 
#27

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 14:11
Der Aufruf passierte laut Stacktrace 67 Zeilen weiter unten ab dem begin des Execute gezählt. Da ist im geposteten Quelltext ein end. Da müsstest du noch einmal schauen, was dort vorher stand.
Im geposteten Quellcode wurden die Aufrufe für mein Logging entfernt - deswegen die Diskrepanz.

Das wäre dann die Zeile
Delphi-Quellcode:
                        // Methode direkt aufrufen:
                        try
--> _evTimerFunc( Self );
                        except
Und wenn nun ohne ProcessMessages die Anwendung hängt... sieht der Bugreport noch genauso aus? Dein Timer nutzt ja nicht immer Synchronize. Kann es vorkommen, dass es ohne aufgrufen wird und dort etwas mit der VCL passiert?
es ist auch aktuell die o.a. Zeile...

Nicht die Statusanzeige oder deren Steuerung gehören in den Thread sondern die lange dauernden Aktionen selbst.
Da gebe ich Dir prinzipiell schon recht, aber das ist auch nicht so einfach.
Da werden externe Prozesse gestartet, Dateien mehrmals hin und her kopiert und angepasst, Reportdaten aktualisiert, eine Paradox-Tabelle mit Daten befüllt und andere Dinge...
...der Ablauf war ursprünglich nicht so aufwändig - es ist aber mit der Zeit immer mehr geworden und jetzt merkt man eben, dass es eine deutlich Verzögerung im Ablauf gibt.

Deswegen der Gedanke mit dem "Bitte warten..."-Dialog, in dem auch die aktuell ausgeführte Aktion textuell angezeigt werden soll.
Da in der ursprünglichen Version der angezeigte Text nicht aktualisiert wurde (bzw. die Aktualisierung nicht angezeigt wurde, hatte ich den Gedanken mit dem Thread, der den Text im Dialog animiert und refresht.


Wenn du im Hauptthread eine Aktion ausführst, kann auch ein Thread keine Aktualisierung der GUI durchführen. Dann bleibt Synchronize schlicht hängen, weil Synchronize voraussetzt, dass der Hauptthread auch funktionsfähig ist, sprich Nachrichten abarbeitet. Das Synchronize wird in WM_IDLE abgearbeitet. Wenn der Hauptthread beschäfitgt ist, passiert das nicht.
Das würde erklären, warum die Dialoganzeige nicht aktualisiert wird...

Alternativ (aber nicht so schön) könntest du auch ein threadbasiertes Fenster anzeigen. Das kann auch direkt aus dem Thread ohne Synchonisierung verwendet werden.
Wenn es da einen "einfachen" Dialog gäbe, dessen Text selber aktualisiert, wäre das nicht schlecht!

https://github.com/jaenicke/MTCL
Da es dafür mittlerweile doch Interesse gibt, arbeite ich daran vielleicht doch mal weiter...
Ich schaue mir die mal an, vielleicht kann ich da was raus extrahieren...


Nur noch was am Rande: MsgWait.. macht innerhalb eines sekundären Threads keinen Sinn da ein solcher Thread keine message queue hat! Er wird also niemals eine input-message (QS_ALLINPUT) bekommen, alle vom Benutzer generierten Messages (mouse, keyboard) landen in der Queue des main threads und der sekundäre thread sieht sie nicht.
Ich sehe schon, ich werde diese Klasse komplett wegschmeissen müssen - die macht so keinen Sinn...


Now to this whole big thread, it is way more complex than it should be.
Thanks a lot for your help / suggestions.
But I'm not sure if I understand everything you mentioned.
Maybe you have some example code for it?

So actually I need a dialog who shows some progress messages - the thread should be able to set the text on that dialog (or the whole dialog is the thread) to show the progress even when the main thread is busy...

EDIT: BTW, the dialog itself could also be a generated native windows dialog - it must not be Delphi at all

Geändert von Bodenseematze ( 1. Feb 2024 um 14:14 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#28

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 14:20
Der ganze Ansatz ist schon komplett für die Füße.
Du musst deine komplexen und langen Operationen in Tasks/Threads packen und die geben zwischendrin oder am Ende Bescheid, was Sachlage ist.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.592 Beiträge
 
Delphi 11 Alexandria
 
#29

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 14:42
Da gebe ich Dir prinzipiell schon recht, aber das ist auch nicht so einfach.
Da werden externe Prozesse gestartet, Dateien mehrmals hin und her kopiert und angepasst, Reportdaten aktualisiert, eine Paradox-Tabelle mit Daten befüllt und andere Dinge...
Wenn du da nicht ran möchtest, bleibt dir nur der Weg über ein Fenster, das außerhalb des Hauptthreads läuft. Da sollte die MTCL in der aktuellen Form schon reichen. Eine Textanzeige und eine ProgressBar hat sie drin.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
353 Beiträge
 
#30

AW: Ursache für hängende Applikation herausfinden

  Alt 1. Feb 2024, 15:28
the thread should be able to set the text on that dialog
That is the problem !

Don't push the info (or data) from background thread to main thread or GUI (VCL), let the VCL/GUI poll the status from the threads, but if it is necessary then notify by (well highly recommended) a message, also make the thread limit its notification to time based condition, like lets say we are moving/copying a folder, if that folder have 10k of small files, it makes no sense to notify or update the UI for each of them, right !?, the copying thread will notify once every 1/10 or 1/20 of second and when finished, and that it is, or will not notify anyone/anything, thread is doing his job and updating single place with data, UI will update with timer, here if the OS itself is way overwhelmed with other application or the CPU is very slow, the application and its UI will not block and will not fail beyond what the OS allow it, but will recover nicely when CPU (hardware in general) is relaxed.

A modal form can block the VCL/GUI/UI.. and show "please wait.." or "working...", while have a timer to get the current status/operation form the worker threads, here you don't need to time your background threads or their operation, they just updating a list (may be a list, or properties ... whatever) in thread safe way, while your dialog or modal form will have a timer and update.

one problem though if the thread operation might take long time and can't be cut or sliced in shorter job, (as example coping 8GB file on SSD or HDD) then nothing can be sliced and here you need to switch to overlapped file operation, https://learn.microsoft.com/en-us/wi...put-and-output

Also look at this nice answers https://stackoverflow.com/questions/...fast-file-copy

Notice also these are not utilizing the overlapped IO, yet these operation (reading/writing) can have it and you can have timeout on any of these operation, also as in the second answer 512KB buffer while the first will be very slow with 1KB, i would suggest to try to perform a read with less than 64KB on any modern hardware to not waste time, and 512KB sound good too with modern hardware cache buffers, in all cases if one of these operation will block for long time then you need to switch to overlapped and use them exactly as sockets !, you call the operation with overlapped structure having an event then poll on that event, in such design you can cancel the operation any time.

The code above can be adjusted to run in background thread and store the current filename(, size, position...etc) inside the thread itself, while your gui with a timer will update the status.

I keep telling that : you should not push form a background thread to main, because i saw this many times, code working perfectly for years, here comes new faster and powerful hardware makes things light speed for UI to keep up, that working code in the past is overwhelming the UI, that happened not because the developer was short sighted, but hardware changed and evolved, few months back i fixed a code (not mine but been asked to modernize it) was working for ages, now it fail with unexpected behavior because the client (owner of that legacy software) started to use hardware with SSD and 2.5Gbs connection, in the past it was on HDD and ADSL.

Hope that helps.
Kas
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz