[英]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
的派生类添加新信号,该类调用操作而不是启动/停止线程。 使用QThreadPool
和QRunnable
任务也是一个好主意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.