AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?
Thema durchsuchen
Ansicht
Themen-Optionen

Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

Ein Thema von DSCHUCH · begonnen am 12. Apr 2013 · letzter Beitrag vom 18. Apr 2013
Antwort Antwort
Seite 1 von 3  1 23      
DSCHUCH

Registriert seit: 6. Jun 2007
Ort: Dresden
185 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#1

Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 12. Apr 2013, 23:54
Hallo,

ich habe jetzt mal noch ein wenig mit dem Problem experimentiert, das Windows immer meldet "Anwendung reagiert nicht mehr" sobald eine Operation länger als ein 3 Sekunden braucht (zumindest, wenn der Anwender noch einmal rumklickt).

Die Variante sämtliche längeren Operationen in Threads auszulagern finde ich ja von vorn herein absolut blödsinnig.

Die Erkenntnis: ich habe eine sehr sehr einfach Lösung gefunden.

In Kurz:

PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);//Refresh Application dies zeichnet alles neu und hält die Anwendung am Leben, Nutzereingaben werden nicht bearbeitet. Ist im MSDN auch genauso beschrieben.
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx

Delphi-Quellcode:
while PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) do;
while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) do;
entfernt sämtliche Nutzereingabe, wodurch verhindert wird, das am Ende einer Schleife alles bearbeitet wird, do der Nutzer während der Wartezeit dumm rumgeklickt hat.

Damit ist eigentlich klar, das anstatt einem Application.ProcessMessages zum Refresh der Anwendung die obigen Befehle aufgerufen werden sollten.

Ich habe somit eine Funktion geschrieben:

Delphi-Quellcode:
procedure TForm11.ApplicationRefresh(RemoveUserInput: Boolean);
var Msg : TMsg;
begin
  PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE);//Refresh Application
  if RemoveUserInput then begin
     while PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) do
           ;//User Mouse Removed
     while PeekMessage(Msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) do
           ;//User Key Removed
  end;
end;
Im Anhang eine ganz einfache Testanwendung. Was haltet Ihr davon?
Angehängte Dateien
Dateityp: zip ApplicationHang.zip (1,8 KB, 22x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#2

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 13. Apr 2013, 00:34
Jo, interessant!

Nenns KeepAlive / Unfreeze das kann man nun als eine andere Option zu Delay sehen ^^
Soetwas müsste man direkt in die oberste Basisklasse für sichtbare Controls packen damit man dann ganz einfach Self/Form1.KeepAlive/Unfreeze aufrufen kann.
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG

Geändert von Aphton (13. Apr 2013 um 00:54 Uhr)
  Mit Zitat antworten Zitat
DSCHUCH

Registriert seit: 6. Jun 2007
Ort: Dresden
185 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#3

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 13. Apr 2013, 00:41
Vor allem macht dies auch automatisch die notwendigen Zeichenoperationen (auch so im MSDN beschrieben).

Letzlich wird ja nicht einmal etwas verändert: die Nachrichtenwarteschlange der Anwendung bleibt, wie sie ist. Die Anwendung arbeitet anschliessend ganz normal weiter. Sämtliche Timer etc verhalten sich ganz normal.

Einzig Windows wird dadurch benachrichtigt, das die Anwendung kontrolliert die Nachrichtenwarteschlange abarbeitet.
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#4

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 13. Apr 2013, 00:46
Ich habs mal ein bisschen umgeschrieben (Class Helper)

Delphi-Quellcode:
type
  // Control-F1: "Controls.TControl is the base class for all components that are visible at runtime."
  // .. und weil nur mit sichtbaren controls interagiert werden kann (onclick, ...), wirds frühestens bei TControl benötigt
  TControlKeepAliveHlp = class helper for TControl
  public
    procedure KeepAlive(const DropUserInput: Boolean = True);
  end;

procedure TControlKeepAliveHlp.KeepAlive(const DropUserInput: Boolean); // "DSCHUSCH"
var
  DummyMsg: TMsg;
begin
  PeekMessage(DummyMsg, 0, 0, 0, PM_NOREMOVE);
  if DropUserInput then
  begin
    while PeekMessage(DummyMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) do;
    while PeekMessage(DummyMsg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) do;
  end;
end;
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#5

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 13. Apr 2013, 01:13
@Aphton ich sehe gerade nicht warum das ganze an einem Control hängen soll, es wird doch die Messagepipe mit 0, also für alle Handles abgefragt und (teil)geleert.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#6

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 13. Apr 2013, 01:43
Hmm..
Schlag was was besseres vor.

Das ist das, worauf ich auf die schnelle gekommen bin. Ich dachte mir, dass man, wenn man schon auf so Sachen wie delay() und eben dann keepAlive() ausweicht, schlechtes Design anwendet (GUI/Logik Trennung) und wenn man schon Dirty-Dinge macht - also in der GUI (sichtbare Controls -> Basisklasse Control) Berechnungen durchführt, dann kann man ja direkt hier mit keepAlive() ansetzen.

das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#7

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 15. Apr 2013, 21:37
schlechtes Design anwendet (GUI/Logik Trennung) und wenn man schon Dirty-Dinge macht
Das mit der Trennung kriegt man auch noch hin. Man könnte ApplicationRefresh/keepAlive ja auch in einem Callback (á la onProgress) aufrufen.


Schlag was was besseres vor.
Delphi-Quellcode:
procedure keepAlive(const DropUserInput: Boolean); // "DSCHUSCH"
var
  DummyMsg: TMsg;
begin
  PeekMessage(DummyMsg, 0, 0, 0, PM_NOREMOVE);
  if DropUserInput then
  begin
    while PeekMessage(DummyMsg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) do;
    while PeekMessage(DummyMsg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) do;
  end;
end;



@DSCHUSCH: Coole Lösung
Intellekt ist das Verstehen von Wissen. Verstehen ist der wahre Pfad zu Einsicht. Einsicht ist der Schlüssel zu allem.
  Mit Zitat antworten Zitat
DSCHUCH

Registriert seit: 6. Jun 2007
Ort: Dresden
185 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#8

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 15. Apr 2013, 22:35
Blumen auch an Himitsu, er hat die Grundidee erarbeitet.

Ja - so habe ich das jetzt auch testhalber in Verwendung - callbacks, welche die Application am Leben halten, ohne das man sonstwas bauen muß. Die Anwendung ist geblockt aber reagiert für Windows (kein Hang), Nutzereingaben werden ignoriert, genauso wie es sein muß. Das alles ohne Disable/Enable und wtf ever für einen blödsinnigen, aufwendigen Nudelcode, der sowieso nur zu Nebeneffekten führt. (zB da durch Application.ProcessMessages ja auch Timer aufgerufen werden können).

Funktionieren tut das aber auch nur aus dem Hauptthread heraus. Die Anwendung muß also nach wie vor vernünftig designed sein.

Achtung - beim Testen im Debugger verhält sich das anders, als wenn die Anwendung ohne Debugger läuft - Delphi hält die Debug-Anwendung hier sicher selbst am Leben, damit Windows nicht meckert "Anwendung reagiert nicht".

Geändert von DSCHUCH (15. Apr 2013 um 22:41 Uhr)
  Mit Zitat antworten Zitat
DSCHUCH

Registriert seit: 6. Jun 2007
Ort: Dresden
185 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#9

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 15. Apr 2013, 23:36
Kann dies mal jemand auf Windows Vista/XP/8 probieren? Die Testanwendung bietet ja die Option mit dem Radiobutton die Funktion an- und abzuschalten.
  Mit Zitat antworten Zitat
anro78

Registriert seit: 24. Okt 2005
25 Beiträge
 
#10

AW: Application - Hang (Anwendung Reagiert nicht) bei längeren Operationen: Lösung?

  Alt 16. Apr 2013, 08:55
Zitat:
Die Variante sämtliche längeren Operationen in Threads auszulagern finde ich ja von vorn herein absolut blödsinnig.
Aber genau das macht man, wenn man eine Anwendung robust entwickeln will, alles andere ist doch nur Herumdoktern an den Symptomen. Was machst du denn z.B. bei einer SQL-Abfrage, die einige Sekunden dauert? Dann hast du gar keine Möglichkeit ApplicationRefresh aufzurufen! Die Implementierung von Threads zur Ausführung von Abarbeitungs-Jobs außerhalb des VCL-Mainthreads ist nun wirklich kein Teufelszeug und innerhalb weniger Minuten implementiert. Man hat die Möglichkeit, den Nutzer über eine Statusanimation entweder definiert (Progress) oder undefiniert (Marquee) über den Fortschritt zu informieren, die Anwendung bleibt weiterhin reaktionsfähig (kann z.B. minimiert oder das Fenster verschoben werden). Und eine Funktion, die sämtliche Top-Level-Controls in einem Fenster während der Abarbeitung sperrt ist auch schnell geschrieben.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      

 

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 01:00 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