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

Call Qt object method from another std::thread

本文关键字:Qt 对象 方法 调用 thread 另一个 std      更新时间:2023-10-16

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

void gui_popup::on_pushButton_clicked()
{
    QString text = ui->MainText->toPlainText();
    text = "1n" + text;
    ui->MainText->setText(text);
}

我也有一些代码,在另一个线程中运行,创建如下:

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

然后,在某个时刻或条件代码需要调用 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、发射信号和所有其他建议的解决方案要复杂得多。但是,谢谢大家的帮助。

我通常这样解决:

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::AutoConnectionQt::ConnectionType类型)。这会告诉 QT 将不同的信号分散到 qt 主事件循环中,如果它们来自外部线程。请注意,使用此连接类型 essentialy 会使 qt 在运行时决定是调度信号还是立即调用时隙。

马丁

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