AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Sleep bei hoher Systemauslastung zu lang
Thema durchsuchen
Ansicht
Themen-Optionen

Sleep bei hoher Systemauslastung zu lang

Ein Thema von SevenOfNine · begonnen am 24. Sep 2007 · letzter Beitrag vom 24. Sep 2007
Antwort Antwort
SevenOfNine

Registriert seit: 11. Jan 2007
Ort: Giessen, Mittelhessen
41 Beiträge
 
Delphi 7 Professional
 
#1

Sleep bei hoher Systemauslastung zu lang

  Alt 24. Sep 2007, 14:21
Hallo zusammen,

in meinem Programm nutze ich folgende "Pause"-Funktion, basierend auf MsgWaitForMultipleObjects:

Delphi-Quellcode:
procedure Wait2(Milliseconds: Integer);
var
  Tick: DWord;
  Event: THandle;
begin
  Event := CreateEvent(nil, False, False, nil);
  try
    Tick := GetTickCount + DWord(Milliseconds);
    while (Milliseconds > 0) and
          (MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) <> WAIT_TIMEOUT) do
    begin
      Application.ProcessMessages;
      if Application.Terminated exit;
      Milliseconds := Tick - GetTickcount;
    end;
  finally
    CloseHandle(Event);
  end;
end;
Die Pause beträgt 1s. Mein Programm läuft mit normaler Priorität.

Bei hoher Systemauslastung erhöht sich die Pause erheblich, ich vermute Timeout von MsgWaitForMultipleObjects funktioniert nicht richtig.

Zu Testzwecken habe ich die Pausefunktion Wait2(1000) einfach durch Application.ProcessMessages ersetzt. Mein Programm läuft hierbei ausreichend schnell ab, ich denke also, dass ich die Priorität nicht erhöhen muss. Mit Sleep(1000) gibt es einen ähnlichen Effekt wie mit Wait2(1000).

Vielleicht weiß hier jemand einen Rat,

beste Grüße
Seven
Mein Kindheitstraum: Die 32bit Farbpalette als Bundstiftsammlung.
  Mit Zitat antworten Zitat
messie

Registriert seit: 2. Mär 2005
Ort: Göttingen
1.592 Beiträge
 
Delphi 2009 Professional
 
#2

Re: Sleep bei hoher Systemauslastung zu lang

  Alt 24. Sep 2007, 15:10
Ich hab' es nicht ganz durchschaut aber wenn Du das im Hauptthread ausführst macht das Ding vielleicht dasselbe wie sleep und blockiert die Eventqueue und bremst damit das System aus. Denn während Du auf waitformultpleobjects wartest, steht der Thread still.

Grüße, Messie
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#3

Re: Sleep bei hoher Systemauslastung zu lang

  Alt 24. Sep 2007, 15:11
Du wirst nie, nie eine Pause von 1 ms Sekunde hinbekommen, wenn du Sleep o.ä. benutzt

Der Grund ist einfach, dass Sleep die Zeitscheibe deines Prozesses sofort abgibt, und dir dann garantiert, dass du nach mindestens der angeebenen Zeitspanne wieder dran kommst.

Zeitscheiben sind üblicherweise ein paar Millisekunden groß, so dass bereits ein Sleep(0) eine Verzögerung von über 20 ms geben sollte

Das gleiche Phänomen kann man beim Timer beobachten: Wenn man ihn auf 0 stellt, kommt das Event trotzdem nur alle 20ms

Bei hoher Systemauslastung sind halt andere Prozesse da, die auch Zeit wollen, und so verlängert sich die Zeit entsprechend ...
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#4

Re: Sleep bei hoher Systemauslastung zu lang

  Alt 24. Sep 2007, 17:38
Zitat:
Ich hab' es nicht ganz durchschaut aber wenn Du das im Hauptthread ausführst macht das Ding vielleicht dasselbe wie sleep und blockiert die Eventqueue und bremst damit das System aus. Denn während Du auf waitformultpleobjects wartest, steht der Thread still.
Nein diese Funktion macht genau das Gegenteil von dem was du vermutest.

Es ist aber so das durch den Auruf von Application.ProcessMessages; auch Nachrichten von Messagequeue genommen werden die die komplette Anwendung blockieren können. Zb. wm_NCLButtonDown, alos ein Klick mit der linken Maustaste in die Caption eines TForms. Versuche es und lass dabei die Maus ruhi liegen und die Maustaste gedrückt. Das Windows API für die Fenster verzweigt nämlich intern in eine Schleife die erst verlassen wird wenn man ie Maustaste wieder loßlässt. Das sind alte Artefakte eines veralteten Fensterhandlings im Windows aus 3.1. Zeiten stammend.

Aber das kann auch dir selber passieren. Zb. eine beliebige Nachricht wie wm_Timer verzweigt in ein Timer1.OnTimer() Event das nun beginnt per Delay() ebenfalls zu warten. SOmit haben wird die Situation das aus einem Delay() -> Application.ProcessMessages -> Timer1.OnTimer() -> Delay() -> Application.ProcessMesages; -> usw. -> usw. aufgerufen wird.

Als ich dieses Delay() hier in der DP vorstellte, als bessere Alternative zum noch schlechteren Sleep(), habe ich aber exakt darauf hingeweisen und auch begründet warum ein asynchroner Aufruf von Application.ProcessMessages; in jedem Falle eine schlechte Idee darstellt. Die VCL und Windows arbeiten Event-basiert also sollte man auch Warteschleifen Event-basiert aufbauen und nicht wie mit Sleep() oder Delay() durch Polling. Denn mit diesen Methoden pollt man die vergehende Zeit, bis genügend Zeit vergangen ist, statt wie bei einem Wecker eine Weckzeit einzustellen und dann nur auf das Klingeln des Weckers zu reagieren.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#5

Re: Sleep bei hoher Systemauslastung zu lang

  Alt 24. Sep 2007, 17:44
Zitat:
Vielleicht weiß hier jemand einen Rat,
Die Ursache liegt in der Reaktionszeit von MsgWaitObject(). Diese ist identisch zu einem Sleep() und wrid durch den Tasksheduler von Windows vorgegeben. Das kannst du nicht verändern, es sei denn du setzt die Zeitscheiben die ein Task zugeordnet werden systemweit auf ein kürzeres Interval um, keine gute Idee übrigens.

Die beste Alternative, und auch die richtige, ist es auf Sleep(), Delay() und asynchrones Application.ProcessMessages, zu verzichten. Nehme einen TTimer, setze .Enabled auf False, dann .Interval auf X Millisekunden Warteseit, und dann .Enabled wieder auf True. Dann läuft deine Anwendung so weiter wi gewohnt und nach X Millisekunden lösst der TTimer ein Event aus. Innerhalb dessen dann .Enabled auf False setzen und die jeweilige Aktion ausführen.

Sollten längerdauerende Berechnungen gemacht werden die quasi im Hintergrund ausgeführt werden sollen dann einfach mal über TThread nachdenken.

Gruß Hagen
  Mit Zitat antworten Zitat
SevenOfNine

Registriert seit: 11. Jan 2007
Ort: Giessen, Mittelhessen
41 Beiträge
 
Delphi 7 Professional
 
#6

Re: Sleep bei hoher Systemauslastung zu lang

  Alt 24. Sep 2007, 19:26
Hallo,

jfheins schrieb:
Zitat:
Du wirst nie, nie eine Pause von 1 ms Sekunde hinbekommen, wenn du Sleep o.ä. benutzt Wink
... ja ich weiß, ich benötige auch 1s, nicht 1ms, wobei ein Fehler von 20ms in meinem Fall nicht tragisch wäre.


Hagens (negaH) Routine mit MsgWaitForMultipleObjects habe ich in einem anderen Projekt schon mal erfolgreich eingesetzt, danke übrigens. Dort kommuniziere ich alle 20ms mit einem an USB angeschlossenem Gerät und stelle Parameterdaten und Diagramm am PC dar. Das funktioniert sehr gut. Zuerst hatte ich das über TTimer realisiert, allerdings macht bei 20ms der Timer-Event Probleme, der erfolgt nämlich nicht so schnell, das liegt wohl am Zeitscheibenmodell von Windows.

negaH schrieb:
Zitat:
Nehme einen TTimer, setze .Enabled auf False, dann .Interval auf X Millisekunden Warteseit, und dann .Enabled wieder auf True. Dann läuft deine Anwendung so weiter wi gewohnt und nach X Millisekunden lösst der TTimer ein Event aus. Innerhalb dessen dann .Enabled auf False setzen und die jeweilige Aktion ausführen.
So wie ich dich verstehe, den Timer im Hauptthread einstellen und aktivieren. Dann im Hauptthread im Prinzip "schlafen" gehen, das heisst zum Beispiel einen OnButtonPress-Event o.ä. beenden.
Die eigentliche Routine erfolgt dann nach dem eingestellten TimerIntervall und wird in OnTimer-EreignisRoutine ausgeführt, wobei man zuvor den Timer deaktiviert und nach der Routine wieder aktiviert, wenn die Routine periodisch aufgerufen werden soll. Ich probiere das mal aus, und beobachte, wie sich das bei hoher Systembelastung verhält.

Gruß
Seven
Mein Kindheitstraum: Die 32bit Farbpalette als Bundstiftsammlung.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#7

Re: Sleep bei hoher Systemauslastung zu lang

  Alt 24. Sep 2007, 23:14
Naja, wenn du alle 20ms ein Event benötigst dann wird das damit nicht gehen. Sowas ist schon schwieriger sauber unter Windows hinzubekommen. Ich würde dann Thread's benutzen, mit höher Priorität. Denoch bleibt der Tasksheduler von Windows und der sorgt dafür das Echtzeit unter Windows eben bei circa 20 Millisekunden und weniger aufhört zu existieren (aus Sicht einer Anwendung auf Ring 3, mit Kerneltreibern kommt man schon noch weiter runter )

Zitat:
und nach der Routine wieder aktiviert, wenn die Routine periodisch aufgerufen werden soll. Ich probiere das mal aus, und beobachte, wie sich das bei hoher Systembelastung verhält.
Da hast du keine Chancen. Bei hoher Systemauslastung werden fast immer alle Anwendungen drunter leiden, zb. das leidige Thema mit den USB-Mäusen/Keyboards die immer schwammiger reagieren bis sie stehen bleiben. Es ist eben im Grunde ein kooperatives Multitasking, auch wenn man es als präemptives Multitasking verkauft. Man kann mit einem einzigsten Thread das System quasi lahmlegen und damit dies nicht passiert muß sich der Thread, bzw. der Programmierer dessen, auch kooperativ verhalten und Rechenzeit abgeben. Eigentlich sollten wir das schon oft erlebt haben, der Explorer kopiert viele große Dateien übers Netzwerk, dann startet man par Anwendungen und das System schläft immer mehr ein. Möchte man den Task-Manager starten hängt der auch noch.

Gruß Hagen
  Mit Zitat antworten Zitat
Antwort Antwort


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:20 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