Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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
Multithreading 使用QT和GUI复制文件的正确方法避免冻结_Multithreading_Qt_User Interface_Freeze_Qfile - Fatal编程技术网

Multithreading 使用QT和GUI复制文件的正确方法避免冻结

Multithreading 使用QT和GUI复制文件的正确方法避免冻结,multithreading,qt,user-interface,freeze,qfile,Multithreading,Qt,User Interface,Freeze,Qfile,我有一个应用程序,它使用QFile::copy(..)将文件从一个位置复制到另一个位置。复制过程是在一个单独的线程中执行到一个worker对象中的,然而,有时候GUI会冻结,我在这里读了很多关于这个的主题,但是我知道这个方法(worker类)是正确的。我在其他项目上也采用同样的方法,在另一个线程(如计时器)中执行进程,它工作得非常好、平滑。似乎只有在复制文件时才会发生这种小冻结。在MS Windows中,“滞后”比在Linux中更为明显,在最后一种情况下,除非复制一个大文件(700MB),否则不

我有一个应用程序,它使用
QFile::copy(..)
将文件从一个位置复制到另一个位置。复制过程是在一个单独的线程中执行到一个worker对象中的,然而,有时候GUI会冻结,我在这里读了很多关于这个的主题,但是我知道这个方法(worker类)是正确的。我在其他项目上也采用同样的方法,在另一个线程(如计时器)中执行进程,它工作得非常好、平滑。似乎只有在复制文件时才会发生这种小冻结。在MS Windows中,“滞后”比在Linux中更为明显,在最后一种情况下,除非复制一个大文件(700MB),否则不会检测到冻结,但只有在文件结束复制时,在复制过程中,GUI才会响应。我在我的
main窗口(BUMain)
类中使用了这种方法:

void BUMain::initThreadSetup()
{
    thread = new QThread;
    Worker *worker = new Worker();
    worker->moveToThread(thread);

    connect(worker,SIGNAL(worker_Signal_updateProgressBar(int)),ui->progressBar,SLOT(setValue(int)),Qt::QueuedConnection);
    connect(this,SIGNAL(main_signal_copyFile(int,QStringList,QString)),worker,SLOT(worker_Slot_copyFile(int,QStringList,QString)),Qt::QueuedConnection);
    connect(worker,SIGNAL(worker_signal_keepCopying()),this,SLOT(main_slot_keepCopying()),Qt::QueuedConnection);
    connect(worker,SIGNAL(worker_signal_logInfo(QString)),gobLogViewer,SLOT(logger_slot_logInfo(QString)),Qt::QueuedConnection);

    connect(thread,SIGNAL(finished()),worker,SLOT(deleteLater()));
    connect(thread,SIGNAL(finished()),thread,SLOT(deleteLater()));
    thread->start();

}
在MainGui(BUMain)构造函数中调用此方法以启动线程。一些相关代码:

这是在发出
worker\u信号\u keepCopying()
时调用的插槽:

void BUMain::main_slot_keepCopying()
{
    giProgress ++;
    if(giProgress < giFileCounter){
        emit(main_signal_copyFile(giProgress,gobPaths,ui->toFilesTextField->text()));
    }
}
工人h:

#ifndef WORKER_H
#define WORKER_H

#include <QObject>
#include <QThread>
#include <QStringList>

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);

signals:
    void worker_Signal_updateProgressBar(int value);
    void worker_signal_keepCopying();
    void worker_signal_logInfo(QString info);

public slots:
    void worker_Slot_copyFile(int liIndex, QStringList files, QString path);

};

#endif // WORKER_H
我希望尽可能清楚,这有点难以解释。我以工人阶级的方法作为参考

注意:我使用QT5.1.1编程,使用Windows 10,使用Arch Linux部署应用程序


任何帮助或建议都将不胜感激。提前谢谢,祝你有愉快的一天

你的方法是正确的,如果有点冗长的话。“滞后”可能是由于内核愚蠢地管理页面缓存,并逐出应用程序的某些部分,以便为正在复制的文件中的页面腾出空间。唯一的补救办法可能是使用特定于平台的文件复制机制,该机制通知内核您将按顺序读取和写入,并且在完成写入后不再需要数据。有关详细信息和一些Linux代码,请参阅。在Windows上,人们希望
CopyFileEx
能够提供正确的建议,a.

为您的答案提供了很多帮助。我来看看。顺致敬意,
#ifndef WORKER_H
#define WORKER_H

#include <QObject>
#include <QThread>
#include <QStringList>

class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = 0);

signals:
    void worker_Signal_updateProgressBar(int value);
    void worker_signal_keepCopying();
    void worker_signal_logInfo(QString info);

public slots:
    void worker_Slot_copyFile(int liIndex, QStringList files, QString path);

};

#endif // WORKER_H
void Worker::worker_Slot_copyFile(int liIndex,QStringList files,QString path)
{
    QString fileName;
    for(int liIndex = 0; liIndex < files.length() - 1; liIndex ++){
        fileName = QFileInfo(files.at(liIndex)).baseName()+"."+QFileInfo(files.at(liIndex)).completeSuffix();

        if (QFile::exists(path+"/"+fileName))
        {
            QFile::remove(path+"/"+fileName);
        }

        QFile lobFile(files.at(liIndex));

        if(lobFile.copy(path+"/"+fileName)){
            emit(worker_signal_logInfo("File: " + fileName + " copied to: " + path));
            emit(worker_Signal_updateProgressBar(liIndex+1));
        }
    }
}