PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Loop ohne CPU Belastung


Jesus
2004-08-12, 10:54:55
hallo,

ich habe gerade ein ganz dummes problem. Ich versuche auf ein Fenster zu "warten" , bzw darauf dass es geschlossen wird.

ich mache folgendes dabei:

while(FindWindow(NULL,"windowname"))
{
MSG msg;

while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

Jedoch habe ich immer noch 100% CPU auslastung.
Muss ich das anders angehen oder ist ein Fehler im obigen Code ? :ugly:

/EDIT: Das Fenster auf das ich warte ist nicht meins ;) es gehört zu einem anderen Programm.

Xmas
2004-08-12, 11:38:10
Ja, das musst du anders angehen. Es gibt ja nichts in deinem Code das "bremsen" würde.

Geht es wirklich um ein Fenster oder um einen Prozess?
Auf einen Prozess kannst du mit WaitForSingleObject (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waitforsingleobject.asp) mit Timeout warten, ansonsten bleibt wohl nur Polling mit einem Timer.

Jesus
2004-08-12, 11:43:34
nein ist leider ein Fenster ;)

aber das sollte doch in etwa dem DoEvents() aus C# entsprechen oder ? Zumindest sollte die CPU nicht durch den while loop blockiert werden da alle messages verarbeitet werden.

aber naja bleibt wohl nix anderes übrig ;)

Xmas
2004-08-12, 11:56:13
DoEvents verwendet aber AFAIK GetMessage statt PeekMessage. GetMessage lässt deinen Thread schlafen, wenn keine Message ansteht, PeekMessage kehrt sofort zurück. Das ist nur sinnvoll, wenn du eine Anwendung hast, die ständig etwas machen soll, auch ohne dass eine Message ansteht (z.B. Animation).

Bestimmte Funktionen der WinAPI (z.B. GetMessage, WaitMessage, und einige andere Wait-Funktionen) lassen deinen Thread schlafen, bis ein Ereignis auftritt. Rufst du keine dieser Funktionen auf, hast du 100% CPU-Auslastung.

In deinem Fall würde wohl ein Timer reichen, der jede Sekunde kurz prüft, ob das Fenster noch da ist. Dann musst du aber GetMessage statt PeekMessage verwenden.

Jesus
2004-08-12, 13:14:57
ok thx.

Einfachkrank
2004-08-12, 14:52:07
Ich glaube es würde auch schon helfen, wenn du das PeekMessage() gegen GetMessage() austauschst...

zeckensack
2004-08-12, 14:55:03
while(FindWindow(NULL,"windowname"))
{
MSG msg;

while(0==PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
{
Sleep(0);
}
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}*nicht getestet*

Einfachkrank
2004-08-12, 15:01:34
while(FindWindow(NULL,"windowname"))
{
MSG msg;

while(0==PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
{
Sleep(0);
}
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Kommt das dann nicht ungefähr aufs selbe raus, wenn man wie ich schon sagte statt dem PeekMessage() das GetMessage() nimmt? *FrageAnDenExperten* :biggrin:

zeckensack
2004-08-12, 15:19:43
Kommt das dann nicht ungefähr aufs selbe raus, wenn man wie ich schon sagte statt dem PeekMessage() das GetMessage() nimmt? *FrageAnDenExperten* :biggrin:Jein. GetMessage liefert genau dann 0 zurück, wenn eine WM_QUIT-Nachricht abgeholt wurde. Ansonsten wartet es unbegrenzt lang auf Nachrichten. Wenn ich das Konstrukt richtig verstanden habe, soll die Message-Pumpe aber so lange laufen, wie das Fenster exisitert. Wird das überwachte Fenster durch eine externe Aktion geschlossen, die von der Message-Pumpe nicht erfasst wurde, bekommst du mit GetMessage einen "infinite loop".

Ob die beiden Lösungen äquivalent sind, hängt maßgeblich davon ab, ob das überwachte Fenster vom gleichen Prozess/Thread erzeugt wurde, in der die Message-Pumpe läuft. Ich gehe aufgrund der "ungewöhnlichen" Implementierung davon aus, dass das nicht der Fall ist, und stattdessen das Fenster eines anderen Prozesses überwacht wird.

Jesus
2004-08-12, 16:59:04
stimmt GetMessage macht nen endlos hänger ;)

habs jetzt mit timer und timerproc gemacht , ist zwar nicht so schön aber funzt.

ttttttttttttt
2004-08-15, 17:42:05
Xmas: Ich glaube DoEvents verwendet PeekMessage. Die Funktion bearbeitet doch nur alle Nachrichten die in der Message Queue sind und wenn alle bearbeitet sind, ist die Funktion vorbei.

Xmas
2004-08-16, 14:46:48
Stimmt, da hatte ich wohl Application.Run() stattdessen im Sinn.