#ifndef Thread_CopyFile_H
#define Thread_CopyFile_H
#include
class Thread_CopyFile : public QThread
{
Q_OBJECT
public:
Thread_CopyFile(QObject * parent = 0);
protected:
void run(); // 新线程入口
signals:
void percentCopied(double percent);
void finished();
void errorOccurred();
public slots:
void cancelCopy();
private:
bool m_canceled;
};
#endif // Thread_CopyFile_H
#include "Thread_CopyFile.h"
#include
#include
#include "common.h"
#include
Thread_CopyFile::Thread_CopyFile(QObject *parent)
: QThread(parent)
{
// 新线程的初始化不要放在这里
}
void Thread_CopyFile::run()
{
// 新线程入口
// 初始化和操作放在这里
m_canceled = false;
QFile src(SrcFile);
QFile cpy(CpyFile);
qint64 srcSize = QFileInfo(src).size();//9000
int bytesWritten = 0;
if (srcSize==0 || !src.open(QFile::ReadOnly))
{
emit errorOccurred();
return;
}
if (cpy.exists())
{
cpy.resize(0);//清空目标txt内容
}
if (!cpy.open(QFile::WriteOnly))
{
src.close();
emit errorOccurred();
return;
}
qDebug()<<"curThreadId()=="<<QThread::currentThreadId();
while (!src.atEnd())
{
if (m_canceled)
{
src.close();
cpy.close();
cpy.remove();
return;
}
msleep(8);
qint64 wrt = cpy.write(src.readLine());//9
if (wrt < 0)
{
emit errorOccurred();
src.close();
cpy.close();
cpy.remove();
return;
}
bytesWritten += wrt;
emit percentCopied(bytesWritten*1.0/srcSize);//返回百分比
}
src.close();
cpy.close();
emit finished();
}
void Thread_CopyFile::cancelCopy()
{
m_canceled = true;
}
#ifndef OBJECT_COPYFILE_H
#define OBJECT_COPYFILE_H
#include
class Object_CopyFile : public QObject
{
Q_OBJECT
public:
explicit Object_CopyFile(QObject *parent = 0);
signals:
void percentCopied(double percent);
void finished();
void errorOccurred();
public slots:
void startCopying();
void cancelCopying();
private:
bool m_canceled;
};
#endif // FILECOPIER_H
#include "Object_CopyFile.h"
#include "common.h"
#include
#include
#include
#include
Object_CopyFile::Object_CopyFile(QObject *parent) : QObject(parent)
{
// 这个类与多线程的实现没有直接的关系,它就老老实实地做好自己的事情
m_canceled = false;
}
void Object_CopyFile::startCopying()
{
qDebug()<<"curThreadId()=="<<QThread::currentThreadId();
m_canceled = false;
QFile src(SrcFile);
QFile cpy(CpyFile);
qint64 srcSize = QFileInfo(src).size();
int bytesWritten = 0;
if (srcSize==0 || !src.open(QFile::ReadOnly))
{
emit errorOccurred();
return;
}
if (cpy.exists())
{
cpy.resize(0);
}
if (!cpy.open(QFile::WriteOnly))
{
src.close();
emit errorOccurred();
return;
}
while (!src.atEnd())
{
if (m_canceled)
{
src.close();
cpy.close();
cpy.remove();
return;
}
QThread::msleep(8);
qint64 wrt = cpy.write(src.readLine());
if (wrt < 0)
{
emit errorOccurred();
src.close();
cpy.close();
cpy.remove();
return;
}
bytesWritten += wrt;
emit percentCopied(bytesWritten*1.0/srcSize);
}
src.close();
cpy.close();
emit finished();
}
void Object_CopyFile::cancelCopying()
{
m_canceled = true;
}
private:
Ui::MainWindow *ui;
Thread_CopyFile *m_Thr; // 用于复制文件的子线程
Object_CopyFile *m_Obj; // 用户复制文件的类
QThread *m_Thread; // m_Obj将被移动到此线程执行
Object_CopyFile *m_Obj2;// 用户复制文件的类
//方式一 自定义线程,继承QThread重写run()函数,复制任务在run中完成
m_Thr = new Thread_CopyFile(this);
connect(m_Thr, SIGNAL(errorOccurred()),this, SLOT(errorHandleSlot()));
connect(m_Thr, SIGNAL(percentCopied(double)),this, SLOT(updateCopyProgress(double)));
connect(m_Thr, SIGNAL(finished()),this, SLOT(copyFinishSlot()));
//方式二 继承QObject,使用MoveToThread
m_Obj = new Object_CopyFile; // 这个实例要负责复制任务,不要设置parent
m_Thread = new QThread; // 子线程,本身不负责复制
// 将实例移动到新的线程,实现多线程运行
connect(this, SIGNAL(startCopyRsquested()), m_Obj, SLOT(startCopying()));
connect(this, SIGNAL(cancelCopuRequested()), m_Obj, SLOT(cancelCopying()));
connect(m_Obj, SIGNAL(errorOccurred()),this, SLOT(errorHandleSlot()));
connect(m_Obj, SIGNAL(percentCopied(double)),this, SLOT(updateCopyProgress(double)));
connect(m_Obj, SIGNAL(finished()),this, SLOT(copyFinishSlot()));
m_Obj->moveToThread(m_Thread);
//connect(m_childThread,SIGNAL(started()),m_copier,SLOT(startCopying())); //开启线程槽函数
//m_Thread->start(); //启动子线程
//单线程(继承QObject,不使用MoveToThread)
m_Obj2 = new Object_CopyFile;
connect(this, SIGNAL(startCopyRsquested2()), m_Obj2, SLOT(startCopying()));
connect(this, SIGNAL(cancelCopuRequested2()), m_Obj2, SLOT(cancelCopying()));
connect(m_Obj2, SIGNAL(errorOccurred()),this, SLOT(errorHandleSlot()));
connect(m_Obj2, SIGNAL(percentCopied(double)),this, SLOT(updateCopyProgress(double)));
connect(m_Obj2, SIGNAL(finished()),this, SLOT(copyFinishSlot()));
...
void MainWindow::on_btnCopy1_clicked()
{
m_Thr->start(); // 复制文件的新线程开始(用start()自动调用run())
}
void MainWindow::on_btnCopy2_clicked()
{
qDebug()<<"Main btnCopy2 threadId()=="<<QThread::currentThreadId();
m_Thread->start(); //需start才能有效传信号槽
emit startCopyRsquested(); //m_childThread不start时槽函数不响应
}
void MainWindow::on_btnCopy3_clicked()
{
qDebug()<<"Main btnCopy3 threadId()=="<<QThread::currentThreadId();
emit startCopyRsquested2();
}
以文件复制为例将继承QThread、QObject,两种Qt多线程方式作简单对比
Github某星夜之夏
Qt使用多线程的一些心得——2.继承QObject的多线程使用方法