以下代码可以正常运行:
self.sim.create_pnl_results(gui_values, dfs)
此代码给出了一个错误:
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)
似乎应用程序在某个地方进一步调用了一个com对象,因为我想把一个gui(QT)置于顶部,我需要将它作为一个单独的线程。如何避免上述错误消息?我已经读过它与Windows问题有关。任何建议如何在python中解决它将不胜感激。我无法控制从应用程序调用的com对象,我不明白为什么如果我从新线程的主线程中调用它们会有所不同。
有关如何调用com对象的其他信息:
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 ()
答案 0 :(得分:1)
如果您尝试从另一个线程更新/重绘UI,许多(如果不是大多数)GUI应用程序会遇到问题。试想一下,如果你有一个线程试图将“蓝色”100x写入文件,而另一个线程试图写入“红色”100x,会发生什么。你会看到类似的东西:
redblueredblruede...
(用Python授予你GIL所以你可能得不到同样的效果,但使用多处理你可能会让它成为现实。)
如果一个线程试图将区域变为蓝色,而另一个线程试图将其变为红色,则图形应用程序将完全相同。因为这是不可取的,所以有一些警卫可以通过抛出你遇到的异常来阻止它发生。
你在这里发生的事情是这样的:
----(UI Thread)-,----------------->
\
`---(new thread)-----(affect the UI)-X kaboom!
你想要发生的事情是这样的:
----(UI Thread)-,--------------------------------------,---(affect the UI)-->
\ /
`---(new thread)-----(pass result)-`
它的确切机制将从框架变为框架。在.NET中,你有一个if (thing.InvokeRequired){ thing.BeginInvoke(data); }
在Windows上,COM对象受到同样的保护。如果在线程上创建COM对象,则不希望您尝试在其他线程上访问它。因此,如果您在另一个线程上创建它,并且仍然需要与它进行交互,那么您将不得不跨线程进行通信。
如果您的代码没有阻塞,或者运行时间不长(即<250ms),那么在主线程上运行调用应该没问题。通常,UI框架允许您注册一个在N
时间后执行的回调,然后只要它可以在主线程上执行。