Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Shaun E on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Reduce CPU load 2

Status
Not open for further replies.

guitardave78

Programmer
Sep 5, 2001
1,294
GB
I have an app that loops through a specified directory and its sub directories and catalogs them to a database.

While this is running task manager shows it as not responding. Can this be stopped from happening?

Also is it possible to force an app to not run at a high priority ie can i stop the loop from using 90% of my cpu? set it to low priority or somthing?

cheers guys
 
You may want to try putting a DoEvents in somewhere.

Andy
"Logic is invincible because in order to combat logic it is necessary to use logic." -- Pierre Boutroux
"A computer program does what you tell it to do, not what you want it to do." -- Greer's Third Law
 
Hi there,

Pulled this straight from MSDN:

Yields execution so that the operating system can process other events.

Syntax

DoEvents( )

Remarks

The DoEvents function returns anInteger representing the number of open forms in stand-alone versions of Visual Basic, such as Visual Basic, Professional Edition. DoEvents returns zero in all other applications.

DoEvents passes control to the operating system. Control is returned after the operating system has finished processing the events in its queue and all keys in the SendKeys queue have been sent.

DoEvents is most useful for simple things like allowing a user to cancel a process after it has started, for example a search for a file. For long-running processes, yielding the processor is better accomplished by using a Timer or delegating the task to an ActiveX EXE component.. In the latter case, the task can continue completely independent of your application, and the operating system takes case of multitasking and time slicing.

Caution Any time you temporarily yield the processor within an event procedure, make sure theprocedure is not executed again from a different part of your code before the first call returns; this could cause unpredictable results. In addition, do not use DoEvents if other applications could possibly interact with your procedure in unforeseen ways during the time you have yielded control.


Hope it helps.

Harold

***You can't change your past, but you can change your future***
 
for example

while i<10000
doEvents
print i
i=i+1
wend

now in every loop it will leave cpu for other waiting processes on DoEvents statement, and will print i when it will get cpu again.
 
mm small cpu load reduction, but does stop it from saying it is not responding :)

nice
 
The small cpu load reduction is because of you're using all time assigned by windows to your thread for processing stuff. This will not affect other applications that are of equal priority as your thread, however; if they need their part of the assigned cpu time, they will use it.

Whenever you're NOT waiting for any windows messages you'll be consuming CPU resources more than usual. This is not something to be alarmed about, however; it's quite normal.

Greetings,
Rick
 
ok thanks. I just thought that you would be able to asign vb6 to a low priority!!

Just a pain when you are looping and loging through every file on your drive lol.

Sure there will be more questions soon (like how to watch a drive for changes)

cheers
 
Watch a drive for changes? Heh, see my code in thread222-576673...
 
nice but a little unstable!! locks up and can't terminate it from button 2!!!
 
sorry didnt mean to offend, will give me a nice starting point :)
(wish i had vb.net, acheive the same result in half the code :()
 
You can pause your application's thread for small time intervals which has the effect of giving it a lower process priority:
Code:
Public Type FILETIME
	dwLowDateTime As Long
	dwHighDateTime As Long
End Type

Public Const WAIT_ABANDONED = &H80&
Public Const WAIT_ABANDONED_0 = &H80&
Public Const WAIT_FAILED = -1&
Public Const WAIT_IO_COMPLETION = &HC0&
Public Const WAIT_OBJECT_0 = 0
Public Const WAIT_OBJECT_1 = 1
Public Const WAIT_TIMEOUT = &H102&

Public Const INFINITE = &HFFFF
Public Const ERROR_ALREADY_EXISTS = 183&

Public Const QS_HOTKEY = &H80
Public Const QS_KEY = &H1
Public Const QS_MOUSEBUTTON = &H4
Public Const QS_MOUSEMOVE = &H2
Public Const QS_PAINT = &H20
Public Const QS_POSTMESSAGE = &H8
Public Const QS_SENDMESSAGE = &H40
Public Const QS_TIMER = &H10

Public Const QS_MOUSE = (QS_MOUSEMOVE _
Or QS_MOUSEBUTTON)

Public Const QS_INPUT = (QS_MOUSE _
Or QS_KEY)

Public Const QS_ALLEVENTS = (QS_INPUT _
Or QS_POSTMESSAGE _
Or QS_TIMER _
Or QS_PAINT _
Or QS_HOTKEY)

Public Const QS_ALLINPUT = (QS_SENDMESSAGE _
Or QS_PAINT _
Or QS_TIMER _
Or QS_POSTMESSAGE _
Or QS_MOUSEBUTTON _
Or QS_MOUSEMOVE _
Or QS_HOTKEY _
Or QS_KEY)

Declare Function CreateWaitableTimer Lib &quot;kernel32&quot; _
Alias &quot;CreateWaitableTimerA&quot; ( _
Byval lpSemaphoreAttributes As Long, _
Byval bManualReset As Long, _
Byval lpName As String) As Long

Declare Function OpenWaitableTimer Lib &quot;kernel32&quot; _
Alias &quot;OpenWaitableTimerA&quot; ( _
Byval dwDesiredAccess As Long, _
Byval bInheritHandle As Long, _
Byval lpName As String) As Long

Declare Function SetWaitableTimer Lib &quot;kernel32&quot; ( _
Byval hTimer As Long, _
lpDueTime As FILETIME, _
Byval lPeriod As Long, _
Byval pfnCompletionRoutine As Long, _
Byval lpArgToCompletionRoutine As Long, _
Byval fResume As Long) As Long

Declare Function CancelWaitableTimer Lib &quot;kernel32&quot; ( _
Byval hTimer As Long) As Long

Declare Function CloseHandle Lib &quot;kernel32&quot; ( _
Byval hObject As Long) As Long

Declare Function WaitForSingleObject Lib &quot;kernel32&quot; ( _
Byval hHandle As Long, _
Byval dwMilliseconds As Long) As Long

Declare Function MsgWaitForMultipleObjects Lib &quot;user32&quot; ( _
Byval nCount As Long, _
pHandles As Long, _
Byval fWaitAll As Long, _
Byval dwMilliseconds As Long, _
Byval dwWakeMask As Long) As Long
'__________________________________

Public Sub sWait(Byval lngInterval As Long)
		
	'--- Pauses the application thread for the specified number of milliseconds
	
	'--- Parameters
	'	[In]
	'	lngInterval: the number of millisecs to pause for
	
	Dim dblDelay As Double  'Pause interval converted to nanoseconds
	Dim dblDelayLow As Double  'Low order 32 bits of a 64 bit date/time value
	Dim dblUnits As Double  'Units in nanoseconds
	Dim lngBusy As Long  'MsgWaitForMultipleObjects function return value
	Dim lngRtn As Long  'General function return value
	Dim hTimer As Long  'Handle to the timer
	Dim strTimerName As String  'Name of timer
	Dim udtFT As FILETIME  'Filetime structure to initialize the timer
	
	'Create the timer
	strTimerName = &quot;My Apps Timer&quot; & Chr$(0)
	hTimer = CreateWaitableTimer(0, True, strTimerName)
	
	'Initialize the timer
	udtFT.dwLowDateTime = -1
	udtFT.dwHighDateTime = -1
	lngRtn = SetWaitableTimer(hTimer, udtFT, 0, 0, 0, 0)
	
	' Convert the units and delay interval to nanoseconds.
	dblUnits = Cdbl(&H10000) * Cdbl(&H10000)
	dblDelay = Cdbl(lngInterval) * 10000
	
	' By setting the high/low time to a negative number, it tells
	' the Wait (in SetWaitableTimer) to use an offset time as
	' opposed to a hardcoded time. If it were positive, it would
	' try to convert the value to GMT.
	udtFT.dwHighDateTime = -Clng(dblDelay / dblUnits) - 1
	dblDelayLow = -dblUnits * (dblDelay / dblUnits - _
	Fix(dblDelay / dblUnits))
	
	If dblDelayLow < Cdbl(&H80000000) Then
     	' &H80000000 is MAX_LONG, just making sure
		' that we don't overflow when we stick it into
		' the FILETIME structure.
		dblDelayLow = dblUnits + dblDelayLow
	End If
	
	udtFT.dwLowDateTime = Clng(dblDelayLow)
	lngRtn = SetWaitableTimer(hTimer, udtFT, 0, 0, 0, False)
	
	Do
		' QS_ALLINPUT means that MsgWaitForMultipleObjects will
		' return every time the thread in which it is running gets
		' a message. If you wanted to handle messages in here you could,
		' but by calling Yield we are letting DefWindowProc
		' do its normal windows message handling---Like DDE, etc.
		lngBusy = MsgWaitForMultipleObjects(1, hTimer, False, _
		INFINITE, QS_ALLINPUT)
		Yield
	Loop Until lngBusy = WAIT_OBJECT_0
	
	' Close the handle
	CloseHandle hTimer
	
End Sub
I used to use this a lot on W98 systems where some batch processes, particularly involving late bound ActiveX servers, would send CPU usage to 100% and the system would grind to a halt. You can let the user select a processor priority from 10 to 1 and assign a pause value in millisecs based on the selection. Then at the end of each loop call sWait.

Select Case cboPriority.Text
Case &quot;10&quot; : lngPause = 0
Case &quot;9&quot; : lngPause = 50
Case &quot;8&quot; : lngPause = 100
'and so on
End Select

Do ....
'.....
sWait lngPause
Loop

Paul Bent
Northwind IT Systems
 
[3eyes]
Geeee, Paul! That's some great stuff.
I won't wait to see if it works with Dave's problem. I'll play around with this - and give you a vote as rent...
;-)
Andy

Andreas Galambos
EDP / Technical Support Specialist
Bowne Global Solutions Wuppertal, Germany
(andreas.galambos@bowneglobal.de)
HP:
 
ok so do i put the code in a module and then call sWait 100
in a loop ?
 
this seems to work well
Private Declare Sub Sleep Lib &quot;kernel32&quot; (ByVal dwMilliseconds As Long)

sleep 10

pauses the function over millisecond
slows the app but reduces to about 20% cpu

higher the sleep number the longer the pause the lower the cpu load!!
 
Sleep pauses an application for a specified period but has the disadvantage that it pauses the thread that the application is running in, and that any window that the application has open will not repaint properly. This may present an unattractive user interface.

An alternative to Sleep is to use SetWaitableTimer, which will allow the screen to repaint, receive DDE messages, and so forth.

Paul Bent
Northwind IT Systems
 
one more, sorry, really noob question. How do i stop a loop from a command button
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top