我有一个按钮点击触发的功能。执行时,它会迭代给定目录中的文件,读取每个文件,然后通过套接字连接将内容发送到客户端。对于发送的每个文件,内容将写回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);
}
答案 0 :(得分:0)
MainView::sendDirectoryFiles
未在工作线程中执行,因为connect
默认使用Qt::AutoConnection
,这意味着在插槽对象的线程中调用该函数,即{{1在你的例子中。您可以通过明确选择this
:
Qt::DirectConnection
进一步考虑
请注意connect(&mSendDirectoryFilesThread, SIGNAL(started()), this, SLOT(sendDirectoryFiles()), Qt::DirectConnection);
应该是线程安全的,但实际情况并非如此。例如,您正在通过调用MainView::sendDirectoryFiles
来更改GUI,这是不允许的。
您可能还想在ui->btnStopSendingDirectoryFiles->setEnabled(true);
结束时调用mSendDirectoryFilesThread.exit(0)
,否则您将无法在不首先明确停止操作的情况下执行两次操作。
如H. Gomaa所指出的那样使用MainView::sendDirectoryFiles
可能是一个更清晰的解决方案,但被调用的方法应该仍然是线程安全的。
您可以考虑向派生类QtConcurrent::run
添加新信号,该类调用操作而不是启动/停止线程。使用QThreadPool
和QThread
任务也是一个好主意。