我的线程工作不好,它给出了所有结果,最后没有一个接一个,GUI 在线程运行期间挂起?
my thread is not working well it gives all result, together at last not one by one & GUI is got hanged during thread run?
我想在用户选择的特定位置按名称搜索文件。我想要在拿到文件后立即这样做。它必须并行放在QTreeWidget中,并在搜索过程中显示QMovie(":/images/img_searching.gif"),直到用户没有停止搜索。
ThreadSearch.h
#ifndef QTHREADSEARCH_H
#define QTHREADSEARCH_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <QFileInfoList>
class QThreadSearchFileName : public QThread
{
Q_OBJECT
public:
QThreadSearchFileName(QObject *parent = 0);
~QThreadSearchFileName();
void run();
void getAllfiles(QStringList, QDir);
signals:
void fileInfoList(QFileInfo);
private:
QMutex m_Mutex;
QWaitCondition m_WaitCondition;
};
#endif
线程搜索.cpp
#include "ThreadSearch.h"
#include <QApplication>
#include <QThread>
QThreadSearchFileName::QThreadSearchFileName(QObject *parent):QThread(parent)
{
}
QThreadSearchFileName::~QThreadSearchFileName()
{
m_WaitCondition.wakeOne();
wait();
}
void QThreadSearchFileName::run()
{
QMutexLocker locker(&m_Mutex);
}
void QThreadSearchFileName::getAllfiles(QStringList targetStrList, QDir currentdir)
{
for(long int i1=0; i1<targetStrList.size(); i1++)
{
QString targetStr;
targetStr = targetStrList[i1];
QDirIterator it(currentdir, QDirIterator::Subdirectories);
while (it.hasNext())
{
QString filename = it.next();
QFileInfo file(filename);
if (file.isDir())
{ // Check if it's a dir
continue;
}
if (file.fileName().contains(targetStr, Qt::CaseInsensitive))
{
emit fileInfoList(file);
}
}
}
}
主.cpp
#include <QCoreApplication>
#include <QDebug>
#include <QDirIterator>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThreadSearchFileName *m_pSearchFileNameThread = new QThreadSearchFileName;
for(int i=0; i<userSelectedpathList.size(); i++)
{
QDir dir(userSelectedpathList[i]);
m_pSearchFileNameThread ->getAllfiles(stringListToBeSearch, dir);
connect(m_pSearchFileNameThread,SIGNAL(fileInfoList(QFileInfo)),this,SLOT(searchFileNameResult(QFileInfo)));
}
return a.exec();
}
void main::searchFileNameResult(QFileInfo file1) //Now Making SearchFile Name Tree
{
QTreeWidgetItem *SearchTreeItem = new QTreeWidgetItem(m_psearchProgresswdgt->finalSearchList_treeWidget);
SearchTreeItem->setCheckState(0,Qt::Unchecked);
SearchTreeItem->setText(1,file1.baseName());
}
最好将
此类操作与 GUI 对象分开。更重要的是,我建议QObject提供的更高级别的异步机制:
例如,创建一些可以处理搜索的类搜索类:
class SearchingClass : public QObject { Q_OBJECT public: void setSomeSearchParametersOrSomething(QObject* something); public slots: void search(); signals: void found(QObject* objectThatHasBeenFound); }
创建此类的实例并将其移动到另一个线程中:
auto searchingObject = new SearchingClass(); searchingObject->setSomeSearchParametersOrSomething(...); auto thread = new QThread(); searchingObject->moveToThread(thread); connect(this, SIGNAL(startSearchingSignal()), searchingObject, SLOT(search())); connect(searchingObject, SIGNAL(found(QObject*)), this, SLOT(someHandleFoundSlot(QObject*))); emit startSearchingSignal();
确保每次搜索算法找到某些结果时都会发出找到的信号。
Ofc 你必须实现 someHandleFoundSlot 并在 GUI 类中声明 startSearchingSignal 信号。
我假设你几乎不了解Qt框架,所以你应该阅读信号和插槽以及Qt元对象系统,以完全理解整个代码。
编辑:我看到您已经编辑了您的问题。你的问题有几个解决方案,我会描述你,你做错了什么,与我在这里发布的内容相比。
- 不要延长
QThread
。改为扩展QObject
。它使你可以调用moveToThread
方法。创建QThread
的实例并将其传递给此方法。它会导致稍后在您传递的线程中执行插槽。 - 不要在循环中建立相同的连接,直到您希望多次执行它。
- 将方法
getAllfiles
(或在我的示例中search
)设置为插槽,不要手动调用它。手动调用方法时,它将始终在同一线程中执行。只需将其连接到某个信号,然后发出该信号。[就像您在找到匹配文件时发出信号一样 - 结果正在插槽对象线程中处理。
这是 - 您的决定,如果你想为每个
userSelectedpathList
元素都有线程。我建议您在一个工作线程中执行此操作(这是磁盘操作,我认为它不会更快)并在getAllfiles
方法中迭代该列表。
之前我给了你关于"如何在Qt中进行异步工作"的通用答案。这是您的用例的简单实现(我希望您能学到一些东西)。
主.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
主窗口.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QFileInfo>
#include <QDirIterator>
#include <QThread>
#include <QDebug>
#include <QPushButton>
#include "filesearchingclass.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0){
setCentralWidget(&pushButton);
connect (&pushButton, SIGNAL(clicked(bool)), this, SLOT(main())); //invoke this->main() in event loop when button is pressed
qRegisterMetaType<QFileInfo>("QFileInfo");
searchingThread.start(); //thread must be started
}
~MainWindow(){
searchingThread.quit();
searchingThread.wait();
}
public slots:
void main() {
//EXAMPLE PARAMETERS:
QStringList pathList;
pathList.append("/home");
pathList.append("/var/log");
QStringList stringListToBeSearch;
stringListToBeSearch.append(".jpg");
stringListToBeSearch.append(".log");
//-------------------
auto fileSearchingObject = new FileSearchingClass(); //dynamic as you can't destroy object when it is out of scope
fileSearchingObject->moveToThread(&searchingThread); //important!!!
fileSearchingObject->setTargetStrList(stringListToBeSearch);
fileSearchingObject->setPaths(pathList);
connect(this,SIGNAL(startSearching()),fileSearchingObject,SLOT(search())); //do not call fileSearchingObject->search() manually
connect(fileSearchingObject,SIGNAL(foundFile(QFileInfo)),this,SLOT(searchFileNameResult(QFileInfo))); //handle every result in event loop
connect(fileSearchingObject, SIGNAL(searchFinished()), fileSearchingObject, SLOT(deleteLater())); //no need to wory about deleting fileSearchingObject now
emit startSearching(); //like calling fileSearchingObject->search() but in another thread (because of connection)
}
signals:
void startSearching();
public slots:
void searchFileNameResult(QFileInfo fileInfo) {
//do something
qDebug() << "---FOUND---" << fileInfo.absoluteFilePath() << "n";
}
private:
QThread searchingThread;
QPushButton pushButton;
};
#endif // MAINWINDOW_H
文件搜索类.h
#ifndef FILESEARCHINGCLASS_H
#define FILESEARCHINGCLASS_H
#include <QFileInfo>
#include <QDirIterator>
#include <QThread>
#include <QDebug>
class FileSearchingClass : public QObject {
Q_OBJECT
public:
~FileSearchingClass(){}
void setPaths (const QStringList &paths) {
userSelectedPathList = paths;
}
void setTargetStrList(const QStringList &value) {
targetStrList = value;
}
public slots:
void search() {
for(int i=0; i<userSelectedPathList.size(); i++) {
QDir currentDir(userSelectedPathList[i]);
for(long int i1=0; i1<targetStrList.size(); i1++)
{
QString targetStr;
targetStr = targetStrList[i1];
QDirIterator it(currentDir, QDirIterator::Subdirectories);
while (it.hasNext())
{
QString filename = it.next();
QFileInfo file(filename);
if (file.isDir())
{ // Check if it's a dir
continue;
}
if (file.fileName().contains(targetStr, Qt::CaseInsensitive))
{
emit foundFile(file); //calling MainWindow::searchFileNameResult directly is possible, but bad idea. This thread is only focused in searching, not modifing widgets in GUI.
}
}
}
}
emit searchFinished(); //it's always good to know when job is done.
}
signals:
void foundFile(QFileInfo);
void searchFinished();
private:
QStringList userSelectedPathList;
QStringList targetStrList;
};
#endif // FILESEARCHINGCLASS_H
相关文章:
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 当我在其中一个线程执行中(在activemq-cpp中)捕获到特定值时,我如何终止/停止所有其他线程
- 试图创建一个多线程程序来查找0-100000000之间的总素数
- 为什么一个向量上的多线程操作很慢
- 在另一个线程中调用luaL_error会引发qWarning
- 全局变量 多读取器 一个写入器多线程安全?
- C++一个线程如何正确通信其任务已完成?
- 最佳做法是从另一个线程访问 qml 中的Q_PROPERTY
- C++线程:如何在一个线程仍在运行时阻止另一个线程执行 (Win32)
- 是否可以创建一个从不同类调用函数的线程?
- 如何制作一个只能在一个线程上同时执行的函数?
- 结束另一个线程中使用的对象的生存期
- C++线程安全:如果只有一个线程可以写入非原子变量,但多个线程从中读取. 会遇到问题吗?
- 一个线程等待多个线程事件
- 两个线程一个使用流 Api,另一个线程创建文件失败并出现错误ERROR_SHARING_VIOLATION
- C 两个线程一个用于输入,一个用于输出
- 2个线程 - 一个带有OpenGL窗口的线程,第二个带有WXWIDGETS的窗口
- 每个线程一个类实例,C++11
- 多线程-一个作家和一个读者-我们需要使用储物柜吗
- Cuda如何从全局函数运行多个线程?一个运行多个线程的内核