c++ - 在线程中复制文件以防止应用程序卡住

原文 标签 c++ multithreading qt copy freeze

我编写了具有“安装程序”功能的C ++ / QT应用程序。一切正常,但是当我的程序处于“复制过程”中时,当我在窗口外单击时,它将以某种方式失去焦点并冻结直到复制过程结束,然后一切正常显示,并且QProgressBar值为100%。
我复制像这样:

void Installer_C::copy(QString aSrcPath, QString aDstPath)
{    
  //handles
  hSrc = CreateFileW(..); //source file
  hDst = CreateFileW(..); //destination
  //copy
  ReadFile(...);
  LockFile(...);
  WriteFile(...); //->returnes bytesWritten
  UnlockFile(...);
  updateQProgressBar(bytesWritten); //updates progressbar in my application
  CloseHandle(...);
}


在foreach循环中调用此函数,该循环通过QStringList和文件(位于我的launchInstall()函数中)进行迭代。
由于我的问题,我考虑过为此复制过程创建线程。为每个Installer_C::copy()调用创建一个新线程,还是仅创建一个线程来调用launchInstall()函数(我认为这没有多大帮助)效率更高?或者更好的问题:它甚至可以解决我的问题吗?应用程序冻结的问题?我应该如何做才能使ProgressBar仍从该线程中更新?

最佳答案

我认为,解决问题的最佳方法是创建一个附加线程来复制进程。您可以使用QThread(Qt文档:QThread)类创建一个线程,该线程将复制文件。主线程将执行您的GUI,并且在文件复制期间将可用。

复制线程的小例子:

class CopyThread : public QThread
{
    Q_OBJECT
private:
    QStringList oldfiles_;
    QStringList newfiles_;
public:
    CopyThread(const QStringList& oldfiles,
               const QStringList& newfiles,
               QObject * parent = 0)
        : QThread(parent)
        , oldfiles_(oldfiles)
        , newfiles_(newfiles)
    {}

    void run() Q_DECL_OVERRIDE 
    {
        int min = qMin(oldfiles_.count(), newFiles.count());
        for(int i=0; i<min; ++i)
        {
            copyFile(oldfiles_.at(i), newFiles_.at(i));
            emit signalCopyFile(oldfiles_.at(i), newFiles_.at(i));
        }
    }
signals:
    void signalCopyFile(const QString&, const QString&);
private:
    void copyFile(QString aSrcPath, QString aDstPath)
    {
        QFile::copy(aSrcPath, aDstPath);
    }
};


当然,您必须在窗口小部件上为signalCopyFile(const QString&, const QString&)实现插槽并建立连接。一小段代码(例如)启动复制线程并建立连接:

QStringList oldFiles;
oldfiles.append("C:/1.txt");
QStringList newFiles;
newFiles.append("C:/2.txt");
yourProgressBar.setMaximum(oldFiles.count());
yourProgressBar.setMinimum(0);
yourProgressBar.setValue(0);
CopyThread *copyThread = new CopyThread(oldFiles, newFiles, this);
connect(copyThread, &CopyThread::finished, copyThread, &QObject::deleteLater);
connect(copyThread, &CopyThread::signalCopyFile, youWidget, &YouWidget::yourSlot);
copyThread->start();


yourSlot中,您可以更新QProgressBar的值:

void yourSlot(const QString& oldFile, const QString& newFile)
{
    // your actions when one file was copied
    yourProgressBar->setValue(yourProgressBar.value() + 1);
}


一切都会好起来的,不会冻结!

关于c++ - 在线程中复制文件以防止应用程序卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38047810/

相关文章:

c++ - 按钮图标未在运行时显示

c++ - 使用 OpenCV (C++) 在 Xcode 中访问网络摄像头

c++ - 命名局部变量`property`是否有任何问题?

c++ - MSVS 链接器在静态 const 字符串之间添加数据

c# - C# 静态类私有(private)字段线程安全吗?

c++ - 使用 QPainter 在像素图上绘制带阴影的文本

c++ - 堆内存是每个进程的吗? (或)不同进程共享的公共(public)内存位置?

java - LoadableDetachableModel 多线程问题

python - asyncio.sleep 如何不阻塞线程?

c++ - QT-第三方回拨不回叫?