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 biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

win32api::Sleep(5000) blocking Word and Excel 1

Status
Not open for further replies.
Jun 1, 2004
18
GB
Hi all,

I have built a pretty simple application (with no forms or visual components). The Main entry point calls the following function that checks the current time and loops until it passes a certain time:

Code:
FUNCTION sleepUntil(wakeUpTime)

	PRIVATE hasBeenPrevious, secs
	
	DECLARE Sleep IN Win32API INTEGER
	
	m.secs = SECONDS()
	m.hasBeenPrevious = (m.secs < m.wakeuptime)
	
	* Do this loop until wakeup time overtakes real time
	* but do it at least until 
	DO WHILE m.secs < m.wakeUpTime OR !m.hasBeenPrevious
		? m.secs
		m.secs = SECONDS()
		m.hasBeenPrevious = ((m.secs < m.wakeuptime) OR m.hasBeenPrevious)
		Sleep(5000)
	ENDDO 
	
ENDFUNC

This is compiled into an EXE file (I'm using VFP7.0)

The problem that I am seeing is that, while this EXE is running, Word and Excel applications are running very slow: specifically document open and clipboard paste operations seem to be affected. They seem to be pausing for about 5 seconds: the same time set in the Sleep() function.

If I reduce the sleep time to 500 millis, the apparent pause in word and excel also reduces.

If I kill my application, Word and Excel performance returns to 'normal'.

My understanding of this is that the sleep should only block the current thread: how it can block threads in a separate process space is beyond me. Somehow, am I taking some system wide mutex by calling sleep?

Can anyone tell me what is going on here and how I can fix it?

Thanks
 
Your problem is probably related to this paragraph in MSDN: You have to be careful when using Sleep and code that directly or indirectly creates windows. If a thread creates any windows, it must process messages. Message broadcasts are sent to all windows in the system. If you have a thread that uses Sleep with infinite delay, the system will deadlock. Two examples of code that indirectly creates windows are DDE and COM CoInitialize. Therefore, if you have a thread that creates windows, use MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx, rather than Sleep.

VFP always creates windows (even if they aren't made visibly by your application), and I think Sleep probably (since it blocks your whole thread) intereferes with the main _VFP window's processing of some windows broadcast messages that must be sent by the MS Office programs during open-file operations.

Here's a snippet of code using something similar to the suggested "WaitFor" functions:
Code:
  FUNCTION WaitRd( tnMilliSecs )
    LOCAL hEventRead, nWait, cRead, lRead

    DECLARE INTEGER WSAEventSelect IN ws2_32;
        INTEGER s, INTEGER hEventObject, INTEGER lNetworkEvents

    DECLARE INTEGER WSAWaitForMultipleEvents IN ws2_32;
        INTEGER cEvents, INTEGER @lphEvents, INTEGER fWaitAll,;
        INTEGER dwTimeout, INTEGER fAlertable

    DO WHILE .T. && Loop until nothing is read from the socket.
        * creating event, linking it to the socket and wait
        hEventRead = WSACreateEvent()
        = WSAEventSelect(THIS.hSocket, hEventRead, FD_READ)

        * 1000 milliseconds can be not enough
        THIS.WaitForRead = WSAWaitForMultipleEvents(1, @hEventRead, 0, tnMilliSecs, 0)
        = WSACloseEvent(hEventRead)

        IF THIS.WaitForRead <> 0 && error or timeout
            EXIT
        ENDIF
        lRead = .T.
        * reading data from connected socket
        THIS.cIn = THIS.cIn+THIS.Rd()
    ENDDO
    RETURN lRead
  ENDFUNC
(of course, you'll have to modify this since you're not waiting for a socket read event)

- Bill

Get the best answers to your questions -- See FAQ481-4875.
 
Nice one Bill!

If anyone is interested in the solution, let me know and I'll clean up the code and post it.

Thanks!
 
Glad to help! I wouldn't mind having the cleaner code, too... I use Sleep occasionally and would rather not block the whole computer.

However, I was kind-of limited in my viewpoint in answering your question Can anyone tell me what is going on here and how I can fix it? since I was focused on what was going on...

In my own programs, when I need a VFP program to run like a service but only do something under certain conditions, I usually set a Timer to go off every 500ms or 10sec (or whatever, depending on how responsive it needs to be, and how resource intensive each check is), rather than having a WHILE loop with a Sleep. My main use for Sleep is when I only have to wait a couple times until a certain condition happens.

- Bill

Get the best answers to your questions -- See FAQ481-4875.
 
Note that this needs a bit more investigatation: I would like to know where the events are being processed/handled.

Also, you have to use MsgWaitForMultipleObjectsEx(). The other function, MsgWaitForMultipleObjects(), still blocks other apps.

Code:
* Note that wakeup time is seconds after midnight.
* If the wake up time is earlier in the day than when the
* method is called, then the function will sleep until that 
* time tomorrow i.e. it wakes up only after it passes the 
* given wake up time.
FUNCTION sleepUntil(wakeUpTime)

	PRIVATE hasBeenPrevious, secs
	
	#define MAXSLEEP 500
	
	DECLARE MsgWaitForMultipleObjectsEx IN WIN32API ;
		INTEGER nCount, ;
  		INTEGER @pHandles, ;
  		INTEGER dwMilliseconds, ;
		INTEGER dwWakeMask, ;
		INTEGER dwFlags

	m.secs = SECONDS()
	m.hasBeenPrevious = (m.secs < m.wakeuptime)
	
	* Do this loop until wakeup time overtakes real time
	DO WHILE m.secs < m.wakeUpTime OR !m.hasBeenPrevious
		m.secs = SECONDS()
		m.hasBeenPrevious = ((m.secs < m.wakeuptime) OR m.hasBeenPrevious)
		MsgWaitForMultipleObjectsEx(0, 0, MAXSLEEP, 0x40, 0)
	ENDDO 
	
ENDFUNC
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top