ActiveState Code

Recipe 82236: Flexible Win32 message pump using MsgWaitForMultipleObjects


In win32, as in other event-driven systems, you must process messages or bad things happen. (Or at best, good things don't happen.) The MsgWaitForMultipleObjects is one way to deal with handling messages as well as coordinating several other activities.

Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import win32event
import pythoncom

TIMEOUT = 200 # ms

StopEvent = win32event.CreateEvent(None, 0, 0, None)
OtherEvent = win32event.CreateEvent(None, 0, 0, None)

class myCoolApp:
        def OnQuit(self):
		win32event.SetEvent(StopEvent) # exit msg pump


def _MessagePump():

	while 1:
		
		rc = win32event.MsgWaitForMultipleObjects(
			(StopEvent,OtherEvent), 
			0, # wait for all = false
			TIMEOUT,  #  (or win32event.INFINITE)
			win32event.QS_ALLEVENTS) # type of input

		# You can call a function here if it doesn't take too long.
		#   It will get executed *at least* every 200ms -- possibly
		#   a lot more, depending on the number of windows messages received.

		if rc == win32event.WAIT_OBJECT_0:
			# Our first event listed was triggered.
			# Someone wants us to exit.
			break
		elif rc == win32event.WAIT_OBJECT_0+1:
			# Our second event "OtherEvent" listed was set.
			# This is from some other component -
			#   wait on as many events as you need
		elif rc == win32event.WAIT_OBJECT_0+2:
			# A windows message is waiting - take care of it.
			# (Don't ask me why a WAIT_OBJECT_MSG isn't defined < WAIT_OBJECT_0)
			# Note: this must be done for COM and other windowsy
			#   things to work.
			if pythoncom.PumpWaitingMessages():
				break # wm_quit
		elif rc == win32event.WAIT_TIMEOUT:
			# Our timeout has elapsed.
			# Do some work here (e.g, poll something can you can't thread)
			#   or just feel good to be alive.
			# Good place to call watchdog(). (Editor's note: See my "thread lifetime" recepie.)
			pass
		else:
			raise RuntimeError( "unexpected win32wait return value")

Discussion

This is one possible message pump structure you can use in your win32 application.

Messages and other events will be dispatched as soon as they are posted, and a timeout allows you to poll other components. You may need to poll if the proper calls or event-objects are not exposed to do you bidding in your win32 event loop, as many componets insist on running on the main app's thread and cannot run on spawned threads. (Also see the related "thread lifetime mangement" on polling.)

Sign in to comment