【问题标题】:OpenMP, QTextEdit and QPlainTextEditOpenMP、QTextEdit 和 QPlainTextEdit
【发布时间】:2015-07-04 13:51:40
【问题描述】:

在尝试了我所知道的一切之后,甚至添加了

QT_MainWindow::QT_MainWindow(QWidget *parent) :QMainWindow(parent), ui(new Ui::QT_MainWindow)
{
    ui->setupUi(this);
    qRegisterMetaType<QTextCursor>("QTextCursor");
    qRegisterMetaType<QTextBlock>("QTextBlock");
}

对于我的来源,我仍然无法在 QTextEdit 和 QPlainTextEdit 中修改来自其他线程的文本,而且我正在使用带有 Qt 的 OpenMP。

谁能告诉我在 QTextEdit 和 QPlainTextEdit 中从其他线程修改文本的正确方法是什么,因为我没有找到任何可以帮助我的东西

这是我的来源:

void QT_MainWindow::Load()
{
    ui->QT_PlainTextEdit->setPlainText("");

    std::ifstream file("File.txt");
    std::string line;
    #pragma omp parallel
    {
    while ( std::getline(file, line) )

    ui->QT_PlainTextEdit->appendPlainText( QString::fromStdString(line));

    file.close();
    }
}

我设法让它像这样工作

void QT_MainWindow::Load()
{
    omp_set_dynamic(0);
    omp_set_nested(3);
    #pragma omp parallel num_threads(3)
    {
      ui->QT_PlainTextEdit->setPlainText("");
    }
}

但如果我尝试设置文本

void QT_MainWindow::Load()
{
    omp_set_dynamic(0);
    omp_set_nested(3);
    #pragma omp parallel num_threads(3)
    {
      ui->QT_PlainTextEdit->setPlainText("TEST");
    }
}

我收到此错误

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

还有

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x465bfc0), parent's thread is QThread(0x3f3ad60), current thread is QThread(0x466d450)QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTextDocument(0x465bfc0), parent's thread is QThread(0x3f3ad60), current thread is QThread(0x46eebe0)HEAP[app.exe]: 
Invalid address specified to RtlFreeHeap( 00000000023F0000, 0000000003F3DC40 )

【问题讨论】:

  • 附点源码就好了,很难说……
  • 好的,等一下我会的
  • @RobertWadowski 好的,我添加了源代码并注意我在运行任何东西之前都会执行 qRegisterMetaType
  • 如果你想从不同的线程加载一些字符串,我认为你对自己来说很复杂。最好将线程源放在 qthread 中并通过信号/插槽进行通信。这不是绝对的 QT 方式....创建工作类,将其放入线程,连接到 ui 插槽,您就有了清晰(和分离)的实现。
  • 我想我找到了原因见stackoverflow.com/questions/16501284/…。好像只有GUI线程可以访问ui和控件

标签: c++ multithreading qt openmp


【解决方案1】:

问题是您在主线程以外的线程中访问 Qt GUI 对象。

来自http://doc.qt.io/qt-4.8/threads-qobject.html

虽然 QObject 是可重入的,但 GUI 类,尤其是 QWidget 和 它的所有子类都是不可重入的。它们只能从 主线程。

解决此问题的一种方法是使用 Qt 信号/插槽使用 QueuedConnection 将来自工作线程的信号连接到主线程中的插槽,但是在您的情况下,我认为这没有多大意义。即使您获得了使用 openmp 的信号,您也无法以并行方式将字符串附加到 QPlainTextEdit 以提高性能。

【讨论】:

    【解决方案2】:

    我设法做到了,我认为它一定比连接插槽简单一点。

    在我的 qt_mainwindow.h 中我只是添加了

    public slots:
        void QT_PlainTextEdit_appendPlainText(QString line);
        void QT_PlainTextEdit_SetText(QString line);
    

    在我的 qt_mainwindow.cpp 中我得到了这些行

    void QT_MainWindow::QT_PlainTextEdit_appendPlainText(QString line)
    {
        ui->QT_PlainTextEdit->appendPlainText(line);
    }
    
    void QT_MainWindow::QT_PlainTextEdit_SetText(QString line)
    {
        ui->QT_PlainTextEdit->setPlainText(line);
    }
    
    void QT_MainWindow::Load()
    {
        #pragma omp parallel num_threads(1)
        {
            std::ifstream file("file.txt");
            std::string line;
    
            while ( std::getline(file, line) )
                QMetaObject::invokeMethod(this,"QT_PlainTextEdit_appendPlainText",Qt::QueuedConnection,Q_ARG(QString,QString::fromStdString(line)));
            file.close();
        }
    }
    

    好吧,我尽可能地尝试了它并没有失败,但我想知道我是否做得正确

    【讨论】:

    • @drescherjm 那么您对此有何看法?
    • 对我来说更好,但我仍然认为应该以 qt 方式完成(至少在我看来)
    • @RobertWadowski 所以你说这是正确的?我不敢相信
    • 我说这是一种更好但不是 qt 方式。您至少正在使用元对象系统。我写了如何使用线程加载数据:)
    • @RobertWadowski 好的,我想知道为什么应用程序仍会进入“无响应”状态
    猜你喜欢
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 2012-07-07
    • 2013-03-02
    相关资源
    最近更新 更多