gpt4 book ai didi

c++ - 如何从其他线程访问QWidget

转载 作者:行者123 更新时间:2023-11-30 04:08:34 25 4
gpt4 key购买 nike

我有

struct MyWidget : QWidget {
// non-GUI related stuff:
int data;
int doSth();
};

我需要从另一个线程(即不是主线程)访问一个 MyWidget 实例。有什么办法可以安全地做到这一点?我知道我无法访问 GUI 相关功能,因为某些后端(例如 MacOSX/Cocoa)不支持。但是,在此示例中,我只需要访问 datadoSth()。但据我所知,根本没有办法保证对象的生命周期 - 即如果带有该小部件的父窗口关闭,MyWidget 实例将被删除。

或者有没有办法保证生命周期?我猜想 QSharedPointer 不起作用,因为 QWidget 在内部执行其生命周期处理,具体取决于父窗口小部件。 QPointer 当然也无济于事,因为它很弱而且没有锁定机制。

我目前的解决方法基本上是:

int widget_doSth(QPointer<MyWidget> w) {
int ret = -1;
execInMainThread_sync([&]() {
if(w)
ret = w->doSth();
});
return ret;
}

(execInMainThread_sync 通过使用 QMetaMethod::invoke 调用主线程中的方法来工作。)

但是,由于某些特定原因,该解决方法不再有效(稍后我将解释原因,但这并不重要)。基本上,那时我无法在主线程中执行某些操作(出于某些复杂的死锁原因)。

我目前正在考虑的另一个解决方法是添加一个全局互斥锁来保护 MyWidget 析构函数,并且在析构函数中,我正在清理对 MyWidget 的其他弱引用。然后,在其他地方,当我需要确保生命周期时,我只需锁定那个互斥量。


我当前的解决方法不再起作用的原因(这仍然是实际情况的简化版本):

  • MyWidget中,data实际上是一个PyObject*

  • 在主线程中,一些 Python 代码被调用。 (在我的应用程序的主线程中完全避免任何 Python 代码调用是不可能的。)Python 代码最终会执行一些 import,它由一些 Python-import-mutex(Python不允许并行导入。)

  • 在其他一些 Python 线程中,调用了其他一些 importimport 现在锁定了 Python-import-mutex。当它在做它的事情时,它会在某个时候进行一些 GC 清理。该 GC 清理调用某个对象的遍历函数,该对象包含该 MyWidget。因此,它必须访问 MyWidget。但是,execInMainThread_sync(或等效的工作解决方案)将死锁,因为主线程当前正在等待 Python 导入锁。

注意:Python 全局解释器锁并不是真正的问题所在。当然,它会在任何 execInMainThread_sync 调用之前解锁。但是,我无法真正检查任何其他潜在的 Python/任何锁。特别是我不被允许只解锁 Python 导入锁——它在那里是有原因的。

您可能会想到的一个解决方案是完全避免在主线程中使用任何 Python 代码。但这有很多缺点,例如它会很慢、复杂且丑陋(GUI 基本上只显示来自 Python 的数据,因此需要一个巨大的代理/包装器来围绕它)。而且我认为我仍然需要在某些时间点等待 Python 数据,所以我只是介绍在其他时间点可能出现的死锁情况。

此外,如果我可以从另一个线程安全地访问 MyWidget,那么所有问题都会消失。与上述相比,引入全局互斥体是更简洁、更短的解决方案。

最佳答案

您可以使用信号/槽机制,但如果 GUI 控件的数量很大,它可能会很乏味。我建议使用单个信号和插槽来控制图形用户界面。发送包含更新 GUI 所需的所有信息的 struct

void SomeWidget::updateGUISlot(struct Info const& info)
{
firstControl->setText(info.text);
secondControl->setValue(info.value);
}

如果收件人被删除,您无需担心发出信号。此细节由 Qt 处理。或者,您可以在退出 GUI 线程事件循环后等待线程退出。你需要 register带有 Qt 的结构。

编辑:

根据我从您的扩展问题中读到的内容,您的问题与线程之间的通信有关。尝试使用管道、(POSIX) 消息队列、套接字或 POSIX 信号代替 Qt 信号进行线程间通信。

关于c++ - 如何从其他线程访问QWidget,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21750947/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com