Python thread: The application called an interface that was marshalled for a different thread

会有一股神秘感。 提交于 2019-12-25 08:14:10

问题


The following code works without errors:

 self.sim.create_pnl_results(gui_values, dfs)

This code gives me an error:

thread = Thread(target=self.sim.create_pnl_results, args=(gui_values, dfs))
thread.start()

in _ApplyTypes_ self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argTypes, *args),
com_error: (-2147417842, 'The application called an interface that was marshalled for a different thread.', None, None)

It seems that the application calls a com object somewhere further down the line and because I would like to put a gui (QT) on top I need to make it a separate thread. How can I avoid the above error message? I have read that it is connected to a windows problem. Any suggestions how to resolve it in python would be appreciated. I have no control on the com objects that are called from the application and I don't see why it would make a difference if I call them from the main thread of a new thread.

additional information about how the com object is called:

def process_ts(*args):
    ts_id, i, dfn , ts_queue = args
    pythoncom.CoInitialize()
    ts = win32com.client.Dispatch(pythoncom.CoGetInterfaceAndReleaseStream(ts_id, pythoncom.IID_IDispatch))
    ts_queue.put( tuple([i , ACRF._com_to_ts(ts, i, dfn)]) )
    pythoncom.CoUninitialize ()

回答1:


Many (if not most) GUI applications run into problems if you try to update/redraw the UI from another thread. Just imagine what would happen if you had one thread trying to write "blue" 100x to a file, and another thread trying to write "red" 100x. You'll see something like:

redblueredblruede...

(granted with Python you have the GIL so you might not get precisely that same effect, but using multiprocessing you could probably make it happen).

The exact same thing would happen to your graphical application if one thread is trying to turn a region blue, while the other is trying to turn it red. Because that's undesirable, there are guards put in place to stop it from happening by throwing exceptions like the one you encountered.

What you have happening here is something like this:

----(UI Thread)-,----------------->
                 \
                  `---(new thread)-----(affect the UI)-X kaboom!

What you want to have happen is something like this:

----(UI Thread)-,--------------------------------------,---(affect the UI)-->
                 \                                    /
                  `---(new thread)-----(pass result)-`

The exact mechanics of it will change from framework to framework. In .NET you've got an if (thing.InvokeRequired){ thing.BeginInvoke(data); }

On Windows, COM objects are protected the same sort of way. If you create an COM object on a thread it doesn't like you trying to access it on a different thread. So if you're creating it on a different thread and you still need to interact with it you're going to have to communicate across your threads.

If your code isn't blocking, or it doesn't take very long to run (i.e. < 250ms) then running the calls on the main thread should be just fine. Typically UI frameworks allow you to register a callback to be executed after N amount of time, and then it will just be executed on the main thread whenever it can be.



来源:https://stackoverflow.com/questions/41192015/python-thread-the-application-called-an-interface-that-was-marshalled-for-a-dif

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!