So, in the light of the tips in Kirk's link (ArcMap Automation: Man the Message Pumps!) and the knowledge that IObjectFactory must be used your scenario, here's my take on Python implementation of the discussed workaround. I am not versed in Python, in fact this might only be my fifth piece of Python code or so, if memory serves. If anyone wants to improve it in any way, go ahead.
import ctypes
import threading
class EsriAppMessageHelper(threading.Thread):
def __init__(self, windowHandle):
threading.Thread.__init__(self)
self.running = True
self.windowHandle = windowHandle
def stop(self):
self.running = False
def run(self):
while self.running:
ctypes.windll.user32.SendMessageA(self.windowHandle, 0, 0, 0)
#print 'WM_NULL to window %d sent' % self.windowHandle
def __enter__(self):
self.start()
def __exit__(self, type, value, traceback):
self.stop()
Basically, it's a thread which sends WM_NULL (0) messages to the given window. The __enter__
and __exit__
functions support Python's with
statement. Here's how it's used (the ArcObjects related functions are taken from this post in a different question):
app = GetApp() # get the IApplication reference
# WM_NULL messages will be sent from another thread while
# this block is executing
with EsriAppMessageHelper(app.hWnd):
objectFactory = CType(app, esriFramework.IObjectFactory) # use IObjectFactory
mxDoc = CType(app.Document, esriArcMapUI.IMxDocument)
graphicsContainer = mxDoc.ActiveView.GraphicsContainer
textElement = CType(objectFactory.Create("esriCarto.TextElement"), esriCarto.ITextElement)
# initialize the symbols and elements, assign their geometries
# etc...
graphicsContainer.AddElement(element, 0)
mxDoc.ActiveView.PartialRefresh(esriCarto.esriViewGraphics, None, None)
# At this point, we're out of the WITH block.
# The separate thread is stopped and no more WM_NULL messages are being sent.
print "DONE"
Try it out. I could not fully test it with my ArcMap 10 setup because I did not have any issues with the active view refresh (it executed immediately and refresh was successful), but the WM_NULL messages do get sent.