从另一个 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 对象方法的主要内容,如果未能解决你的问题,请参考以下文章