c - 将信号从 pthread 发送到 QObject

标签 c qt pthreads signals qtextedit

我会尽量明确。我创建了一个 Qt 应用程序,它有一些按钮和一个 QTextEdit。接下来我创建一个 pthread。并提供指向 MainWindow 的指针作为参数。像这样:

MainWindow w;
pthread_create(&rThread,NULL,treat,&w);

treat是创建线程时执行的函数。现在,如果我有一个名为 myButton 的按钮,并且我在 treat 函数中做了类似这样的事情:

 void *treat(void *arg)
 {
  MainWindow *win = (MainWindow*)arg;
  win->ui->myButton->setEnabled(false);
  close(pthread_self());
 }

它将正常工作,我的应用程序中的 myButton 将被禁用。但是,如果我这样做:

 void *treat(void *arg)
 {
  MainWindow *win = (MainWindow*arg;
  win->ui->editText->setText("random string");
  close(pthread_self());
 }

我的应用程序将因以下错误而崩溃:

QObject: Cannot create children for a parent that is in a different thread. (Parent is QTextDocument(0x23af2e0), parent's thread is QThread(0x209a290), current thread is QThread(0x7f7eec000af0) The program has unexpectedly finished.

据我所知,Ui 存在于主线程中,并且可能无法在我创建的线程中访问,尽管我已将主窗口的指针提供给该线程。但是为什么禁用按钮会起作用?我很困扰。我不使用 QThread 的原因是因为我们的老师告诉我不要这样做。我必须使用 pthreads。我如何将 pthread 中的这种更改应用到 editText ? 我如何将信号从 pthread 发送到 Ui 处于“事件状态”的另一个线程。提前谢谢大家。

最佳答案

一般来说,从 object->thread()< 以外的线程调用任何 QObject(或派生类)方法都是错误的 - 除非它们被设计和记录为线程安全的。 Qt 中有一些方法被明确记录为线程安全的,例如 QCoreApplication::postEvent

您遇到的行为是由于从非 gui 线程访问 QWidget 方法所致。这是未定义的行为,所以有些方法可能会崩溃,有些不会,但即使它们不会崩溃,它仍然是您不能指望的未定义行为。据我们所知,这可能取决于月相。

从另一个线程做的唯一安全的事情是向对象发布一个事件。当您在另一个线程中的对象上使用 QMetaMethod::invokeQMetaObject::invokeMethod 时,Qt 将在内部向该对象发送一个 QMetaCallEvent。由于发布事件是线程安全的(可以从其他线程完成),因此可以从其他线程使用这些调用方法中的任何一个。 QObject::event() 通过执行适当的方法调用对此类事件作出 react 。

因此,您可以从另一个线程做的唯一事情是:

QMetaObject::invokeMethod(win->ui->editText, "setText", Q_ARG(QString, "random string"));

唉,这是糟糕的设计,因为您将 MainWindow 的内部细节(如 ui 指针)暴露给外部。你应该做的是在窗口上有一个 setEditText 槽:

MainWindow : public QWidget {
  ...
public:
  Q_SLOT void setEditText(const QString & str) {
    ui->editText->setText(str);
  }
  ...
};

然后,从另一个线程,你做:

QMetaObject::invokeMethod(win, "setEditText", Q_ARG(QString, "random string"));

我完全同意 Marek R 的建议,当您有可用的 QThread 时不要使用 pthread。

关于c - 将信号从 pthread 发送到 QObject,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21134655/

相关文章:

c++ - 杀死等待条件变量的 pthread

multithreading - pthread_cond_wait 在等待时自动并原子地解锁互斥体

iphone - 在符合协议(protocol)的类中重新声明/扩展 Objective-C 协议(protocol)中定义的 typedef

c++ - 如何使用某些参数展开某个循环,例如 GCC 中的 max-unroll-times

qt - 更改悬停并按下时的 QPushButton 图标

c++ - QTextStream 将错误的数据写入文件

c - 多线程 C qsort char 数组

c - 套接字构建错误

比较 C 中具有任意位数的两个值

c++ - Qt 和 OSG 集成问题,场景图消失