Python线程:该应用程序称为为不同线程编组的接口

时间:2016-12-16 20:29:52

标签: python multithreading win32com

以下代码可以正常运行:

 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 ()

1 个答案:

答案 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时间后执行的回调,然后只要它可以在主线程上执行。