我已經進行了一些研究,但我找不到我的解決方案為什么不起作用的答案。但切中要害。
我在我的應用程式中將 QWidget 作為單獨的對話框。我正在使用這個 QWidget 類來收集檔案的路徑并使用 ZipLib 將它們壓縮到一個檔案中。為了給用戶一些關于壓縮進度的反饋,我添加了 QProgressBar,它在壓縮程序中會更新。但我發現在某些情況下,當檔案太大時,壓縮檔案需要很長時間,并且在此期間我的應用程式沒有回應。所以我的想法是使用 QThread 將長時間的壓縮操作移動到另一個執行緒,一切正常,壓縮作業,進度條更新但是當我想取消壓縮操作時出現問題。使用我當前的壓縮方法操作,不要聽我的任何中斷執行緒的請求,即使在我關閉對話框后執行緒仍在進行壓縮。一世'
tl;博士版本:我不能用requestInterruption()或任何其他方式中斷 QThread。
這是我的 WorkerThread 類:
class WorkerThread : public QThread
{
Q_OBJECT
public:
void setup(std::string zip, std::vector<std::string> file)
{
mZip = zip;
mFiles = file;
mActionStopped = false;
}
void run() override {
size_t progressValue = (100 / mFiles.size());
try
{
for (const auto& file : mFiles)
{
if (not isInterruptionRequested())
{
Q_EMIT updateTheProgress(progressValue);
ZipFile::AddFile(mZip, file);
}
else
{
return;
}
}
}
catch(const std::exception& e)
{
Q_EMIT resultReady(false);
}
if (not mActionStopped)
{
Q_EMIT updateTheProgress(100 - actualProgress); // To set 100%
Q_EMIT resultReady(true);
}
}
std::string mZip;
std::vector<std::string> mFiles;
size_t actualProgress = 0;
bool mActionStopped;
Q_SIGNALS:
void resultReady(bool dupa);
void updateProgress(int value);
public Q_SLOTS:
void updateTheProgress(int value)
{
actualProgress = value;
Q_EMIT updateProgress(actualProgress);
}
void stopWork()
{
mActionStopped = true;
}
};
在我的 QWidget 類中,我有這樣的東西:
workerThread = new WorkerThread();
connect(workerThread, &WorkerThread::resultReady, this, &ZipProjectDialog::zipDone);
connect(workerThread, SIGNAL(updateProgress(int)), progressBar, SLOT(setValue(int)));
connect(btnBox, &QDialogButtonBox::rejected, workerThread, &WorkerThread::requestInterruption);
connect(btnBox, &QDialogButtonBox::rejected, workerThread, &WorkerThread::stopWork);
workerThread->setup(zipFilename, filePathList);
workerThread->start();
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
我已經按照QThread檔案進行了操作,但requestInterruption()仍然無法正常作業。
如果有人知道如何解決這個問題,我將不勝感激。
謝謝!
uj5u.com熱心網友回復:
您不能中斷執行
ZipFile::AddFile(mZip, file);
本身。這是對函式的一次呼叫,沒有人檢查isInterruptionRequested()該函式內部。
一個簡化的例子
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include <QTimer>
class MyThread : public QThread
{
public:
void run() override
{
qDebug() << "starting";
for (int i = 0; i < 10; i) {
qDebug() << "loop" << i;
if (!isInterruptionRequested())
sleep(5);
else
break;
}
qDebug() << "finished";
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyThread thread;
QTimer::singleShot(0, &thread, [&thread] {
thread.start();
QTimer::singleShot(7000 /*7 seconds*/, &thread, [&thread] {
qDebug() << "interrupting";
thread.requestInterruption();
});
});
return a.exec();
}
印刷
starting
loop 0
loop 1
interrupting
loop 2
finished
正如預期的那樣。正如預期的那樣,“中斷”和“回圈 2”之間有幾秒鐘的延遲,“回圈 2”和“完成”之間沒有延遲。
如果你想更細粒度地中斷你的任務,那么你必須找到比 ZipFile::AddFile 更細粒度的 API,這樣isInterruptionRequested()即使單個檔案被歸檔,你也可以定期檢查,或者使用可以被殺死的外部行程。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/478792.html
