Seite 1 von 1
Zeitliche Abfragen im Systray; Suche 'guten/optimalen' Code
Verfasst: 27.06.2009 10:16
von Kaltstart
Ich möchte im Systray eine Anwendung welche mir alle x Minuten eine Systemabfrage startet.
(Im konkreten Fall: -Wieviel Speicherplatz ist noch auf Laufwerk C:, bzw. Sende einen Ping und warte auf Rückmeldung)
Immer mal wieder lese ich im Board dazu Themen über Prozessorauslastung und Timerschleifen, Threads, etc..
Daher wieder einmal meine Frage wie man so etwas am besten 'richtig' programmiert:
- Wie baut man denn grundsätzliche eine Schleife für so eine Anwendung auf?
- Kennt jemand ein 'gutes' Grundgerüst für eine solche Anwendung?
(Mir geht es nur um den Beispiel-Code für die 'Zeitschleife' (Alle z.B: 5 Minuten eine Abfrage; dazwischen 'ruhen' und die anderen Programme (Prozessor,etc..) so wenig als möglich 'stören/belasten'.)
Danke
Kaltstart
Verfasst: 27.06.2009 10:32
von edel
Was du suchst nennt sich
SetTimer. Einfach hier im Forum suchen.
Verfasst: 27.06.2009 10:41
von cxAlex
Einfach via
Timer alle x - Minuten eine Abfrage starten und mit einem Systray - Icon koppeln. So sollte das gehen, die Abfrage musst du noch selbst machen:
Code: Alles auswählen
; ------------------------------------------------------------------------------------
; Easy Timer
; Einfacher leicht erweiterbarer Timer
; PB 4.3 +
; Alexander Aigner
; V 1.0
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
; Internes Zeugs
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
; HighRes - Timer
; ------------------------------------------------------------------------------------
EnableExplicit
Prototype HR_Time()
Structure _HR_Internal
StartTime.q
Res.d
EndStructure
Define _HR._HR_Internal
Global GetTimeMS.HR_Time
Procedure _HR_InitTime()
Shared _HR._HR_Internal
Protected Frequency.q
With _HR
If Not QueryPerformanceFrequency_(@Frequency)
ProcedureReturn #False
Else
QueryPerformanceCounter_(@\StartTime)
\Res = 1000/Frequency
ProcedureReturn #True
EndIf
EndWith
EndProcedure
Procedure _HR_Get()
Shared _HR._HR_Internal
Protected currentTime.q
With _HR
QueryPerformanceCounter_(@currentTime)
ProcedureReturn (currentTime-\StartTime)*\Res
EndWith
EndProcedure
Procedure _HR_oldPC_or_Linux()
ProcedureReturn ElapsedMilliseconds()
EndProcedure
; Initialisierung des High-Res Timers
CompilerIf #PB_Compiler_OS<>#PB_OS_Windows
GetTimeMS = @_HR_oldPC_or_Linux()
CompilerElse
If _HR_InitTime()
GetTimeMS = @_HR_Get()
Else
GetTimeMS = @_HR_oldPC_or_Linux()
EndIf
CompilerEndIf
; ------------------------------------------------------------------------------------
; Eigentlicher Timer
; ------------------------------------------------------------------------------------
Prototype ET_Procedure(Event, UserData)
Enumeration ; Sollte klar sein ...
#ET_Call
#ET_Pause
#ET_Resume
#ET_Free
EndEnumeration
Structure ET_Data
*CB.ET_Procedure
UserData.i
Delay.i
CBEvent.i
CBEventStop.i
CBEventPause.i
EndStructure
Procedure _ET_Thread(*ET.ET_Data)
Protected cTime, wTime
With *ET
wTime = \Delay
Repeat
cTime = GetTimeMS()
While wTime>GetTimeMS()-cTime
Delay(1)
Wend
If \CBEvent ; Nur 1. If-Abfrage für (später) beliebie viele Events
If \CBEventPause ; Pausesignal
\CB(#ET_Pause, \UserData)
WaitSemaphore(\CBEventPause)
\CB(#ET_Resume, \UserData)
EndIf
If \CBEventStop ; Stopsignal
\CB(#ET_Free, \UserData)
SignalSemaphore(\CBEventStop)
ProcedureReturn #Null
EndIf
\CBEvent = #False
EndIf
; Callback aufrufen und Ausgleichszeit errechnen
cTime = GetTimeMS()
\CB(#ET_Call, \UserData)
wTime = \Delay-GetTimeMS() + cTime
; Delay(<0) = warte unendlich
If wTime<0
wTime = #Null
EndIf
ForEver
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Proceduren
; ------------------------------------------------------------------------------------
; Neuen Timer anlegen
Procedure ET_New(*Callback.ET_Procedure, Delay.i, UserData.i)
Protected *ET.ET_Data = AllocateMemory(SizeOf(ET_Data))
With *ET
\CB = *Callback
\Delay = Delay
\UserData = UserData
CreateThread(@_ET_Thread(), *ET)
ProcedureReturn *ET
EndWith
EndProcedure
; Timer pausieren
Procedure ET_Pause(*ET.ET_Data)
With *ET
If Not \CBEventPause
\CBEventPause = CreateSemaphore()
\CBEvent = #True
EndIf
EndWith
EndProcedure
; Timer fortsetzen
Procedure ET_Resume(*ET.ET_Data)
With *ET
If \CBEventPause
SignalSemaphore(\CBEventPause)
FreeSemaphore(\CBEventPause)
EndIf
EndWith
EndProcedure
; Timer freigeben
Procedure ET_Free(*ET.ET_Data)
With *ET
\CBEventStop = CreateSemaphore()
\CBEvent = #True
ET_Resume(*ET) ; Wenn nötig fortsetzen
WaitSemaphore(\CBEventStop)
FreeSemaphore(\CBEventStop)
FreeMemory(*ET)
EndWith
EndProcedure
DisableExplicit
Procedure Test(Event, Dummy)
MessageRequester("Call","Call")
EndProcedure
; Timer auf 1. Minut stellen
Timer = ET_New(@Test(), 1*60000, #Null)
Image = LoadImage(#PB_Any, #PB_Compiler_Home+"Examples\Sources\Data\CdPlayer.ico")
Dummy = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Invisible)
AddSysTrayIcon(#PB_Any, WindowID(Dummy), ImageID(Image))
Popup = CreatePopupMenu(#PB_Any)
MenuItem(1, "Exit")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Menu
Select EventMenu()
Case 1
ET_Free(Timer)
End
EndSelect
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftClick, #PB_EventType_RightClick
DisplayPopupMenu(Popup, WindowID(Dummy))
EndSelect
EndSelect
Until #False
Gruß, Alex
Verfasst: 27.06.2009 13:25
von Kaltstart
Hallo cxAlex,
WOW! Also mit SetTimer(). Danke für den kompletten Beispielcode!
OK.
Mite dem 'EXIT' habe ich noch Probleme. Er führt den Exit erst aus wenn der Timer wieder ausgelaufen ist.
Das muss ich mir jetzt aber dann erst in aller Ruhe 'auseinanderpfümeln'
Gruss
Kaltstart
Verfasst: 05.07.2009 17:33
von cxAlex
Kaltstart hat geschrieben:
Mite dem 'EXIT' habe ich noch Probleme. Er führt den Exit erst aus wenn der Timer wieder ausgelaufen ist.
Hab den Code aktualisiert, nun sollte das Exit sofort ausgeführt werden:
http://www.purebasic.fr/german/viewtopi ... 815#244815
Verfasst: 06.07.2009 00:53
von Kaltstart
Hi cxAlex,
habe die Procedure ausgetauscht.
Nun bleibt er aber komplett hängen.
Schaue es mir morgen/heute nochmals genauer an.
Danke Dir
Gruss
Kaltstart
Verfasst: 06.07.2009 13:20
von cxAlex
So funktioniert bei mir alles korrekt:
Code: Alles auswählen
; ------------------------------------------------------------------------------------
; Easy Timer
; Einfacher leicht erweiterbarer Timer
; PB 4.3 +
; Alexander Aigner
; V 1.0
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
; Internes Zeugs
; ------------------------------------------------------------------------------------
; ------------------------------------------------------------------------------------
; HighRes - Timer
; ------------------------------------------------------------------------------------
EnableExplicit
Prototype HR_Time()
Structure _HR_Internal
StartTime.q
Res.d
EndStructure
Define _HR._HR_Internal
Global GetTimeMS.HR_Time
Procedure _HR_InitTime()
Shared _HR._HR_Internal
Protected Frequency.q
With _HR
If Not QueryPerformanceFrequency_(@Frequency)
ProcedureReturn #False
Else
QueryPerformanceCounter_(@\StartTime)
\Res = 1000/Frequency
ProcedureReturn #True
EndIf
EndWith
EndProcedure
Procedure _HR_Get()
Shared _HR._HR_Internal
Protected currentTime.q
With _HR
QueryPerformanceCounter_(@currentTime)
ProcedureReturn (currentTime-\StartTime)*\Res
EndWith
EndProcedure
Procedure _HR_oldPC_or_Linux()
ProcedureReturn ElapsedMilliseconds()
EndProcedure
; Initialisierung des High-Res Timers
CompilerIf #PB_Compiler_OS<>#PB_OS_Windows
GetTimeMS = @_HR_oldPC_or_Linux()
CompilerElse
If _HR_InitTime()
GetTimeMS = @_HR_Get()
Else
GetTimeMS = @_HR_oldPC_or_Linux()
EndIf
CompilerEndIf
; ------------------------------------------------------------------------------------
; Eigentlicher Timer
; ------------------------------------------------------------------------------------
Prototype ET_Procedure(Event, UserData)
Enumeration ; Sollte klar sein ...
#ET_Call
#ET_Pause
#ET_Resume
#ET_Free
EndEnumeration
Structure ET_Data
*CB.ET_Procedure
UserData.i
Delay.i
CBEvent.i
CBEventStop.i
CBEventPause.i
EndStructure
Procedure _ET_Thread(*ET.ET_Data)
Protected cTime, wTime
With *ET
wTime = \Delay
Repeat
If \CBEvent ; Nur 1. If-Abfrage für (später) beliebie viele Events
If \CBEventPause ; Pausesignal
\CB(#ET_Pause, \UserData)
WaitSemaphore(\CBEventPause)
\CB(#ET_Resume, \UserData)
EndIf
If \CBEventStop ; Stopsignal
\CB(#ET_Free, \UserData)
SignalSemaphore(\CBEventStop)
ProcedureReturn #Null
EndIf
\CBEvent = #False
EndIf
cTime = GetTimeMS()
While wTime>GetTimeMS()-cTime
Delay(1)
If \CBEvent ; Nur 1. If-Abfrage für (später) beliebie viele Events
If \CBEventPause ; Pausesignal
\CB(#ET_Pause, \UserData)
WaitSemaphore(\CBEventPause)
\CB(#ET_Resume, \UserData)
EndIf
If \CBEventStop ; Stopsignal
\CB(#ET_Free, \UserData)
SignalSemaphore(\CBEventStop)
ProcedureReturn #Null
EndIf
\CBEvent = #False
EndIf
Wend
; Callback aufrufen und Ausgleichszeit errechnen
cTime = GetTimeMS()
\CB(#ET_Call, \UserData)
wTime = \Delay-GetTimeMS() + cTime
; Delay(<0) = warte unendlich
If wTime<0
wTime = #Null
EndIf
ForEver
EndWith
EndProcedure
; ------------------------------------------------------------------------------------
; Proceduren
; ------------------------------------------------------------------------------------
; Neuen Timer anlegen
Procedure ET_New(*Callback.ET_Procedure, Delay.i, UserData.i)
Protected *ET.ET_Data = AllocateMemory(SizeOf(ET_Data))
With *ET
\CB = *Callback
\Delay = Delay
\UserData = UserData
CreateThread(@_ET_Thread(), *ET)
ProcedureReturn *ET
EndWith
EndProcedure
; Timer pausieren
Procedure ET_Pause(*ET.ET_Data)
With *ET
If Not \CBEventPause
\CBEventPause = CreateSemaphore()
\CBEvent = #True
EndIf
EndWith
EndProcedure
; Timer fortsetzen
Procedure ET_Resume(*ET.ET_Data)
With *ET
If \CBEventPause
SignalSemaphore(\CBEventPause)
FreeSemaphore(\CBEventPause)
EndIf
EndWith
EndProcedure
; Timer freigeben
Procedure ET_Free(*ET.ET_Data)
With *ET
\CBEventStop = CreateSemaphore()
\CBEvent = #True
ET_Resume(*ET) ; Wenn nötig fortsetzen
WaitSemaphore(\CBEventStop)
FreeSemaphore(\CBEventStop)
FreeMemory(*ET)
EndWith
EndProcedure
DisableExplicit
Procedure Test(Event, Dummy)
If Event = #ET_Call
MessageRequester("Call", "Call")
EndIf
EndProcedure
; Timer auf 1. Minut stellen
Timer = ET_New(@Test(), 1*60000, #Null)
Image = LoadImage(#PB_Any, #PB_Compiler_Home + "Examples\Sources\Data\CdPlayer.ico")
Dummy = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Invisible)
AddSysTrayIcon(#PB_Any, WindowID(Dummy), ImageID(Image))
Popup = CreatePopupMenu(#PB_Any)
MenuItem(1, "Exit")
Repeat
Event = WaitWindowEvent()
Select Event
Case #PB_Event_Menu
Select EventMenu()
Case 1
ET_Free(Timer)
End
EndSelect
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftClick, #PB_EventType_RightClick
DisplayPopupMenu(Popup, WindowID(Dummy))
EndSelect
EndSelect
Until #False
Gruß, Alex
Verfasst: 07.07.2009 01:34
von Kaltstart
Hallo cxAlex,
es funktioniert! (Natürlich

)
Auch wenn ich vom Ablauf her (noch) nicht alles verstehe ist das genau das was ich gesucht habe.
Auf der anderen Seite zeigt es mir aber auch, daß PureBasic genau die Programmiersprache ist, welche ich gesucht habe. (...und sich damit die Programmieranforderungen - welche ich habe - umsetzen lassen.)
Danke und Gruss
Kaltstart