繁体   English   中英

Qt - 在单独线程中运行功能

[英]Qt - Run function in Separate Thread

我有一个按钮单击触发的功能。 执行时,它会迭代给定目录中的文件,读取每个文件,然后通过套接字连接将内容发送到客户端。 对于发送的每个文件,内容将写回gui。 还有一个用于停止迭代的按钮。 截至目前,我正在主线程中处理这个问题,但正如预期的那样,gui变得有些反应迟钝。 我试图在另一个线程中执行该函数但是,我的实现比在主线程中运行更糟糕! 如下所示,一切都在同一个类中。 处理此问题的最佳方法是什么?

private:    
QThread mSendDirectoryFilesThread;

private slots:
void onSendDirectoryFilesClicked();
void onStopSendingDirectoryFilesClicked();
void sendDirectoryFiles();

在类实例化中连接插槽等

moveToThread(&mSendDirectoryFilesThread);
connect(&mSendDirectoryFilesThread, SIGNAL(started()), this, SLOT(sendDirectoryFiles()));

发送按钮点击信号

void MainView::onSendDirectoryFilesClicked()
{
    mSendDirectoryFilesThread.start();
}

发送功能

void MainView::sendDirectoryFiles() {
    QDir packetDir(ui->txtSelectedDirectory->text());
        packetDir.setNameFilters(QStringList() << "*.xml");
    QStringList dirFiles = packetDir.entryList();

    if (dirFiles.count() > 0) {
        ui->btnStopSendingDirectoryFiles->setEnabled(true);

        foreach (QString f, dirFiles) {
            QApplication::processEvents();

            QFile file(ui->txtSelectedDirectory->text() + QDir::separator() + f);
            mDocToSend = getFileXML(file);

            if (mDocToSend.isDocument()) {
                if (mSocket.sendDoc(mDocToSend)) {
                    addToPacketLog(mDocToSend.toString(), "SENT");
                    QThread::sleep(ui->txtTransmitInterval->text().toInt());
                } else {
                    qDebug() << "Nothing to send";
                }
            }
        }
    }
}

停止按钮点击信号

void MainView::onStopSendingDirectoryFilesClicked()
{
    mSendDirectoryFilesThread.exit(0);
}

MainView::sendDirectoryFiles没有在工作线程执行,因为connect采用Qt::AutoConnection默认情况下,这意味着该函数被调用的槽对象的线程,也就是this在你的榜样。 您可以通过显式选择Qt::DirectConnection来更改默认行为:

connect(&mSendDirectoryFilesThread, SIGNAL(started()), this, SLOT(sendDirectoryFiles()), Qt::DirectConnection);

进一步考虑

  • 请注意, MainView::sendDirectoryFiles应该是线程安全的,但实际情况并非如此。 例如,您通过调用ui->btnStopSendingDirectoryFiles->setEnabled(true);来更改GUI ui->btnStopSendingDirectoryFiles->setEnabled(true); ,这是不允许的。

  • 您可能还想在MainView::sendDirectoryFiles的末尾调用mSendDirectoryFilesThread.exit(0) ,否则您将无法在不首先显式停止操作的情况下执行两次操作。

  • 使用H. Gomaa指出的QtConcurrent::run可能是一个更清晰的解决方案,但被调用的方法应该仍然是线程安全的。

  • 您可以考虑向QThread的派生类添加新信号,该类调用操作而不是启动/停止线程。 使用QThreadPoolQRunnable任务也是一个好主意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM