Python 线程:应用程序调用为不同线程编组的接口 [英] Python thread: The application called an interface that was marshalled for a different thread

查看:89
本文介绍了Python 线程:应用程序调用为不同线程编组的接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码可以正常工作:

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)

似乎应用程序在更远的地方调用了一个 com 对象,因为我想把一个 gui (QT) 放在上面,所以我需要使它成为一个单独的线程.如何避免上述错误消息?我读到它与 Windows 问题有关.任何如何在 python 中解决它的建议将不胜感激.我无法控制从应用程序调用的 com 对象,我不明白为什么从新线程的主线程调用它们会有所不同.

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.

有关如何调用 com 对象的其他信息:

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

推荐答案

如果您尝试从另一个线程更新/重绘 UI,则许多(如果不是大多数)GUI 应用程序都会遇到问题.想象一下,如果您有一个线程尝试将蓝色"写入 100x 到一个文件,而另一个线程尝试将红色"写入 100x,会发生什么.你会看到类似的内容:

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...

(如果使用 Python,您拥有 GIL,因此您可能无法获得完全相同的效果,但使用多处理可能会实现).

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

它的确切机制会因框架而异.在 .NET 中,你有一个 if (thing.InvokeRequired){ thing.BeginInvoke(data);}

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

在 Windows 上,COM 对象以同样的方式受到保护.如果你在一个线程上创建一个 COM 对象,它不喜欢你试图在不同的线程上访问它.因此,如果您在不同的线程上创建它并且仍然需要与其交互,则您将不得不跨线程进行通信.

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.

如果您的代码没有阻塞,或者运行时间不长(即 <250 毫秒),那么在主线程上运行调用应该没问题.通常,UI 框架允许您注册要在 N 时间后执行的回调,然后只要有可能,它就会在主线程上执行.

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.

这篇关于Python 线程:应用程序调用为不同线程编组的接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆