我有一个C ++ Qt程序,它使用QThreadPool
来处理不超过MAX_THREAD_COUNT
个线程的文件。我在Qt::QueuedConnection
遇到了麻烦。看起来信号丢失了。但是Qt::DirectConnection
使用它非常完美。
如果有人能解释发生了什么,我会感激不尽。
UPDATE :此代码在Qt中运行良好,但在Visual Studio 2005中运行不正确。在VS中,它在第一个线程完成后停止(但与Qt::DirectConnection
一起使用)
它的外观如下:
Manager.h:
#ifndef MANAGER_H
#define MANAGER_H
#include <QObject>
#include <QThreadPool>
#include <QDebug>
#include "threadbody.h"
class Manager : public QObject
{
Q_OBJECT
private:
QList<QString> processedfiles;
QList<QString> resultfiles;
bool ok;
QString lasterror;
public slots:
void addToProcessedFiles(const QString& filename);
void addToResultFiles(const QString& filename);
void setErrorMessage(const QString& message);
void startNewThread();
public:
bool startManager(const QString& firstfile);
explicit Manager(QObject *parent = 0);
~Manager();
};
#endif // MANAGER_H
ThreadBody.h:
#ifndef THREADBODY_H
#define THREADBODY_H
#include <QTemporaryFile>
#include <QRunnable>
#include <QTextStream>
#define MAX_THREAD_COUNT 4
class ThreadBody : public QObject, public QRunnable
{
Q_OBJECT
private:
QString filename;
public:
ThreadBody(const QString& filename);
~ThreadBody();
void run();
signals:
void sendResult(const QString& filename);
void sendFileName(const QString& filename);
void taskDone();
void threadError(const QString& message);
};
#endif // THREADBODY_H
Manager.cpp:
Manager::Manager(QObject *parent) :
QObject(parent)
{
ok=true;
QThreadPool::globalInstance()->setMaxThreadCount(MAX_THREAD_COUNT);
}
void Manager::addToProcessedFiles(const QString& filename)
{
processedfiles.push_back(filename);
if(QThreadPool::globalInstance()->activeThreadCount()<MAX_THREAD_COUNT)
startNewThread();
}
void Manager::addToResultFiles(const QString& filename)
{
resultfiles.push_back(filename);
}
void Manager::setErrorMessage(const QString& message)
{
ok=false;
lasterror=message;
}
void Manager::startNewThread()
{
if(processedfiles.isEmpty())
return;
if(!ok)
return;
QString filename=processedfiles.takeFirst();
ThreadBody* task=new ThreadBody(filename);
connect(task,SIGNAL(taskDone()),this,SLOT(startNewThread()),Qt::QueuedConnection);
connect(task,SIGNAL(sendResult(const QString&)),this,SLOT(addToResultFiles(const QString&)),Qt::QueuedConnection);
connect(task,SIGNAL(sendFileName(const QString&)),this,SLOT(addToProcessedFiles(const QString&)),Qt::QueuedConnection);
connect(task,SIGNAL(threadError(const QString&)),this,SLOT(setErrorMessage(const QString&)),Qt::QueuedConnection);
qDebug()<<"thread starts";
QThreadPool::globalInstance()->start(task);
}
bool Manager::startManager(const QString& firstfile)
{
processedfiles.push_back(firstfile);
startNewThread();
QThreadPool::globalInstance()->waitForDone();
return ok;
}
Manager::~Manager(){}
ThreadBody.cpp:
#include "threadbody.h"
#include <QThreadPool>
ThreadBody::ThreadBody(const QString& filename)
{
this->filename=filename;
}
ThreadBody::~ThreadBody(){}
void ThreadBody::run()
{
QFile file(filename);
if(!file.open(QIODevice::ReadOnly))
{
QString message=QString("Thread can't open file=%1: %2").arg(filename).arg(file.errorString());
emit threadError(message);
emit taskDone();
return;
}
QTextStream in(&file);
QTemporaryFile newProcessedFile;
newProcessedFile.setAutoRemove(false);
if(!newProcessedFile.open())
{
QString message="Thread can't open temporary file";
emit threadError(message);
emit taskDone();
return;
}
QTextStream out(&newProcessedFile);
QTemporaryFile resultFile;
resultFile.setAutoRemove(false);
if(!resultFile.open())
{
QString message="Thread can't open temporary file";
emit threadError(message);
emit taskDone();
return;
}
QTextStream resultOut(&resultFile);
while(!in.atEnd())
{
//!---time consuming task---!//
//example//
QString currentLine=in.readLine();
out<<currentLine;
resultOut<<currentLine;
}
resultFile.close();
newProcessedFile.close();
file.remove();
emit sendResult(resultFile.fileName());
emit sendFileName(newProcessedFile.fileName());
emit taskDone();
}
main.cpp中:
#include <QCoreApplication>
#include "manager.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Manager manager;
QString filename="C:/airtest/ask.cpp";
manager.startManager(filename);
return a.exec();
}