C++ 我的线程工作不好,它给出了所有的结果,一起最后不是一个接一个&;GUI在线程运行期间被挂起?
我想在用户选择的特定位置按名称搜索文件。我一拿到文件就要。它必须平行放置在QTreeWidget中,并在搜索过程中显示QMovie(:/images/img_search.gif),直到用户没有停止搜索为止 ThreadSearch.hC++ 我的线程工作不好,它给出了所有的结果,一起最后不是一个接一个&;GUI在线程运行期间被挂起?,c++,multithreading,qt,qthread,C++,Multithreading,Qt,Qthread,我想在用户选择的特定位置按名称搜索文件。我一拿到文件就要。它必须平行放置在QTreeWidget中,并在搜索过程中显示QMovie(:/images/img_search.gif),直到用户没有停止搜索为止 ThreadSearch.h #ifndef QTHREADSEARCH_H #define QTHREADSEARCH_H #include <QThread> #include <QMutex> #include <QWaitCondition> #i
#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
#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
#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
\ifndef QTHREADSEARCH\u H
#定义QTHREADSEARCH\u H
#包括
#包括
#包括
#包括
类QThreadSearchFileName:公共QThread
{
Q_对象
公众:
QThreadSearchFileName(QObject*parent=0);
~QThreadSearchFileName();
无效运行();
作废所有文件(QStringList、QDir);
信号:
作废文件信息列表(QFileInfo);
私人:
qmutexm_互斥体;
QWaitCondition m_WaitCondition;
};
#恩迪夫
ThreadSearch.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);
}
}
}
}
#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());
}
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#包括“ThreadSearch.h”
#包括
#包括
QThreadSearchFileName::QThreadSearchFileName(QObject*parent):QThread(parent)
{
}
QThreadSearchFileName::~QThreadSearchFileName()
{
m_WaitCondition.wakeOne();
等待();
}
void QThreadSearchFileName::run()
{
QMutexLocker锁柜(&m_互斥锁);
}
void QThreadSearchFileName::getAllfiles(QStringList targetStrList,QDir currentdir)
{
对于(long int i1=0;i1将此类操作从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必须在GUI类中实现someHandleFoundSlot和声明startSearchingSignal信号
我假设您几乎不了解Qt框架,所以您应该阅读并完全理解整个代码
编辑:
我看到你已经编辑了你的问题。你的问题有几个解决方案,我将描述你,你做错了什么,与我在这里发布的相比
不要扩展QThread
。而是扩展QObject
。它使您可以调用moveToThread
方法。请创建QThread
的实例并将其传递给此方法。这会导致稍后在传递的线程中执行插槽
不要在循环中建立相同的连接,直到您希望它被多次执行
将方法getAllfiles
(在我的示例中是search
)设为slot,不要手动调用它。当手动调用方法时,它将始终在同一线程中执行。只需将它连接到某个信号,并发出该信号。
[就像找到匹配的文件时发出信号一样–结果将在插槽对象线程中处理。]
这是你的决定,如果你想让每个userSelectedpathList
元素都有一个线程。我建议你在一个工作线程中完成(我认为这是磁盘操作,不会更快),并在getAllfiles
方法中迭代该列表
之前我给出了关于“如何在Qt中进行异步工作”的一般答案。下面是一个简单的用例实现(我希望您能学到一些东西)
main.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);
}
}
}
}
#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());
}
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#包括“mainwindow.h”
#包括
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
主窗口w;
w、 show();
返回a.exec();
}
main window.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
#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
#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
\ifndef主窗口
#定义主窗口
#包括
#包括
#包括
#包括
#包括
#包括
#包括“filesearchingclass.h”
类主窗口:公共QMainWindow
{
Q_对象
公众:
主窗口(QWidget*parent=0){
setCentralWidget(&按钮);
连接(&按钮,信号(单击(bool)),此,插槽(main());//按下按钮时在事件循环中调用此->主()
qRegisterMetaType(“QFileInfo”);
searchingThread.start();//必须启动线程
}
~main window(){
searchingThread.quit();
searchingThread.wait();
}
公众时段:
void main(){
//示例参数:
QStringList路径列表;
路径列表。追加(“/home”);
append(“/var/log”);
QStringList stringListToBeSearch;
stringListToBeSearch.append(“.jpg”);
stringListToBeSearch.append(“.log”);
//-------------------
auto-fileSearchingObject=new-FileSearchingClass();//动态,因为当对象超出范围时,您无法销毁它
fileSearchingObject->moveToThread(&searchingThread);//重要!!!
fileSearchingObject->setTargetStrList(stringListToBeSearch);
文件搜索对象->设置路径(路径列表);
连接(this,SIGNAL(startSearching()),fileSearchingObject,SLOT(search());//不要手动调用fileSearchingObject->search()
connect(fileSearchingObject,SIGNAL(foundFile(QFileInfo)),this,SLOT(searchfilenamesult(QFileInfo));//处理事件循环中的每个结果
connect(fileSearchingObject,SIGNAL(searchFinished()),fileSearchingObject,SLOT(deleteLater());//现在不必担心删除fileSearchingObject
emit startSearching();//类似于调用fileSearchingObject->search(),但在另一个线程中(由于连接)
}
信号:
void startSearching();
公众时段:
作废searchFileNameResult(QFileInfo fileInfo){
//做点什么
qDebug()您阅读了的文档了吗?您尝试了什么?有一个很好的示例,说明worker对象应该非常适合您的需要。我发现这篇文章在我第一次执行QThread时非常有用,您不能按值传递QObject,而且这些输入和输出参数根本不应该是QObject。@Frankosterfield您是对的。