我编写了一个具有“安装程序”功能的 C++/QT 应用程序。一切正常,但是当我在程序处于“复制过程”时单击窗口外时,它以某种方式失去焦点并卡住直到复制过程结束,然后一切都正常显示 < strong>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() 函数中)。
由于我的问题,我考虑为这个复制过程创建Threads。是为每个 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/