从另一个 std::thread 调用 Qt 对象方法

Posted

技术标签:

【中文标题】从另一个 std::thread 调用 Qt 对象方法【英文标题】:Call Qt object method from another std::thread 【发布时间】:2014-12-01 14:32:48 【问题描述】:

我有一个简单的 Qt 表单,它代表我的应用程序的主窗口。它有方法:

void gui_popup::on_pushButton_clicked()

    QString text = ui->MainText->toPlainText();
    text = "1\n" + text;
    ui->MainText->setText(text);

我还有一些代码,在另一个线程中运行,像这样创建:

std:thread* core_thread = new thread(&Init); //void Init()...

然后,在某个时刻或来自std::thread 的条件代码需要调用gui_popup::on_pushButton_clicked()。我正在尝试这样做:

void test_callback(void* object_ptr)

    auto this_object = (gui_popup*)object_ptr;
    this_object->on_pushButton_clicked();

在 std::thread 代码中,我保存了 test_callback 指针和 gui_popup 对象指针。但是当它开始调用 on_pushButton_clicked() 时,程序会因分段错误错误而停止。此代码适用于其他一些简单的类,但不适用于 QtObject。我做错了什么?

更新: 我是这样解决的:

void test_callback(void* object_ptr)

    QMetaObject qtmo;
    qtmo.invokeMethod((gui_popup*)object_ptr, "on_pushButton_clicked");

当然,它比使用 QThread、发出信号和所有其他建议的解决方案要复杂得多。不过感谢大家的帮助。

【问题讨论】:

你需要发出信号,而不是直接调用函数 使用 QThread,您可以使用信号和插槽轻松安全地完成此任务。是否有不能使用 Qthread + worker QObject 子类的选项? @BЈовић 你能举例说明如何为某个插槽发出信号吗? @AlekDepler 首先在标头中定义信号,然后在 emit clickPushButton(); 中使用 connect 语句捕获它。 别忘了伙计们,我们只能在 QObject 子类中使用 Qt 信号和槽,并且只能使用 Q_OBJECT 宏。 【参考方案1】:

我通常是这样解决的:

class Foo : public QObject

   Q_OBJECT

     Foo()
     
       // connect to own signal to own slot and hence "translate" it
       connect(this, SIGNAL(some_signal(QString)),
               this, SLOT(some_slot(QString)));
     

   signals:
     void some_signal(QString s);

   protected slots:
     void some_slot(QString s)
     
        // do something with your gui
     
   public: 
     void callback_proxy(std::string s)
     
        emit some_signal(QString::fromUtf8(m_string.c_str()));
     
;

然后胎面就不需要知道QT了:

void thread_run_function(Foo* foo)

    foo->callback_proxy("Hello from Thread!");

据我了解,这是保存,因为连接(信号,插槽)确实有一个额外的默认参数(Qt::ConnectionType 类型默认为Qt::AutoConnection)。这告诉 QT 将信号发送到 qt 主事件循环,如果它们来自外部线程。请注意,使用这种连接类型本质上会让 qt 在运行时决定是调度信号还是立即调用插槽。

HtH 马丁

编辑:有关默认参数的更多信息以及此链接作为参考: 见http://doc.qt.io/qt-5/qt.html#ConnectionType-enum

【讨论】:

以上是关于从另一个 std::thread 调用 Qt 对象方法的主要内容,如果未能解决你的问题,请参考以下文章

Qt + OpenCV 使用 std::thread 播放视频

从不同的 std::thread 更新 Qt GUI

std::thread 消耗 Qt 中的所有 CPU

正如我所料,Qt GUI 不适用于 std::thread

Qt之QThread随记

从具有本地 std::thread 对象的函数中退出而没有加入