Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我的线程工作不好,它给出了所有的结果,一起最后不是一个接一个&;GUI在线程运行期间被挂起?_C++_Multithreading_Qt_Qthread - Fatal编程技术网

C++ 我的线程工作不好,它给出了所有的结果,一起最后不是一个接一个&;GUI在线程运行期间被挂起?

C++ 我的线程工作不好,它给出了所有的结果,一起最后不是一个接一个&;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

我想在用户选择的特定位置按名称搜索文件。我一拿到文件就要。它必须平行放置在QTreeWidget中,并在搜索过程中显示QMovie(:/images/img_search.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
#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您是对的。