I use this solution to get collection of my parsers/wrappers on COM interface objects concurrently. Like this:
def _get_interface_containers_concurrent(
self,
com_interface_containers: List["win32com"],
interface_container_type: Type[InterfaceContainer]
) -> List[InterfaceContainer]:
"""Get interface containers concurrently.
Uses this solution: https://stackoverflow.com/a/27966218/4465708
.. note:: see the class docstring for the current caveats of using this.
:param com_interface_containers: a list of COM objects that correspond to an interface container
:param interface_container_type: a type to wrap with the parser Element object (that wraps the COM one)
:return: a list of wrapped interface containers
"""
def add_ic(id_, repoid, lst: list, ic_type: Type[InterfaceContainer]) -> None:
pythoncom.CoInitialize()
ic_obj = win32com.client.Dispatch(
pythoncom.CoGetInterfaceAndReleaseStream(id_, pythoncom.IID_IDispatch))
repo_obj = win32com.client.Dispatch(
pythoncom.CoGetInterfaceAndReleaseStream(repoid, pythoncom.IID_IDispatch))
ic_el = Element(ic_obj)
print(f"{ic_el.name!r} has been parsed.")
ic = ic_type(ic_el, repo_obj)
lst.append(ic)
print(f"{ic.name!r} {ic_type.__name__} created.")
result, workers = [], []
for com_ic in com_interface_containers:
ic_id = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch, com_ic)
repo_id = pythoncom.CoMarshalInterThreadInterfaceInStream(pythoncom.IID_IDispatch,
self._repo)
t = Thread(target=add_ic, args=(ic_id, repo_id, result, interface_container_type))
workers.append(t)
t.start()
for w in workers:
w.join()
print("Parsing completed.")
return result
This works. At least as long as I only access data parsed and stored on the wrapper objects. As soon as I try to access the wrapped COM object after the threads are joined with the main I get:
com_error: (-2147220995, 'Object is not connected to server', None, None)
Is there some way to get around this? I assume I should probably do something with those COM objects before join. Or maybe, there is some way I can reconnect those objects with the COM server afterwards. Any ideas?
I found a corresponding question on the python-win32
mailing list dating back to 2006. But it seems, even though plenty of time had passed since, there is no answer anywhere for it.