久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

非阻塞工作者 - 中斷文件復制

Non-blocking worker - interrupt file copy(非阻塞工作者 - 中斷文件復制)
本文介紹了非阻塞工作者 - 中斷文件復制的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我正在處理非常大的文件,大小超過數百 GB.用戶需要能夠在磁盤之間移動這些文件,并且在沒有默認文件管理器的受限系統上.用戶有可能意識到他們犯了一個錯誤并取消了操作,據我所知,用戶將不得不等待當前的復制或重命名操作完成.這可能會讓他們感到沮喪,因為他們可能等待幾分鐘,卻發現他們的許多 GB 文件仍在復制.在 Copy 的情況下,我可以刪除第二個文件,但在我用來移動文件的重命名的情況下,我必須反向重復該操作才能撤消它,這是不可接受的.

有什么方法可以中斷我在 QFile 文檔中沒有看到的 copy() 和 rename(),還是我需要將自己的類放在一起來處理復制和重命名?

解決方案

我認為文件大小對重命名需要多長時間沒有任何影響.

對于副本 - Qt 沒有提供任何內置功能,您必須自己實現它.這里的關鍵問題是您必須找到某種方法來連續輪詢副本取消.這意味著你不能為了能夠處理事件而鎖定主線程.

無論您是為了保持主線程響應而使用額外線程,還是決定使用主線程 - 在這兩種情況下,您都需要實現分段"復制 - 使用緩沖區一次一個塊,直到文件被復制或復制被取消.您需要它來處理用戶事件并跟蹤復制進度.

我建議你實現一個 QObject 派生的復制助手工作類,它跟蹤文件名、總大小、緩沖區大小、進度和取消時的清理.那么是選擇在主線程中使用還是在專用線程中使用就是一個選擇了.

找到了,但你最好仔細檢查一下,因為它是作為一個例子完成的并且沒有經過徹底的測試:

class CopyHelper : public QObject {Q_OBJECTQ_PROPERTY(qreal 進度讀取進度寫入設置進度通知進度更改)民眾:CopyHelper(QString sPath, QString dPath, quint64 bSize = 1024 * 1024) :isCancelled(false), bufferSize(bSize), prog(0.0), source(sPath), destination(dPath), position(0) { }~CopyHelper() { free(buff);}qreal progress() const { return prog;}void setProgress(qreal p) {如果 (p != prog) {編 = p;發出progressChanged();}}公共插槽:無效開始(){if (!source.open(QIODevice::ReadOnly)) {qDebug() <<無法開源,中止";發出完成();返回;}文件大小 = source.size();if (!destination.open(QIODevice::WriteOnly)) {qDebug() <<無法打開目的地,正在中止";//也許檢查覆蓋并要求繼續發出完成();返回;}如果 (!destination.resize(fileSize)) {qDebug() <<無法調整大小,正在中止";發出完成();返回;}buff = (char*)malloc(bufferSize);如果(!buff){qDebug() <<無法分配緩沖區,正在中止";發出完成();返回;}QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection);//timer.start();}無效步驟(){如果 (!isCancelled) {如果(位置<文件大小){quint64 塊 = 文件大小 - 位置;quint64 l = 塊 >緩沖區大小 ?緩沖區大小:塊;source.read(buff, l);目的地.write(buff, l);位置 += l;source.seek(位置);目的地.尋求(位置);setProgress((qreal)position/fileSize);//std::this_thread::sleep_for(std::chrono::milliseconds(100));//用于檢測QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection);} 別的 {//qDebug() <<timer.elapsed();發出完成();返回;}} 別的 {if (!destination.remove()) qDebug() <<"刪除失敗";發出完成();}}無效取消(){ isCancelled = true;}信號:void progressChanged();無效完成();私人的:bool 已取消;quint64 緩沖區大小;qreal 程序;QFile 源、目標;quint64 文件大小,位置;字符 * 增益;//QElapsedTimer 定時器;};

done() 信號用于deleteLater() 復制助手/關閉復制對話框或其他任何東西.您可以啟用經過計時器并使用它來實現經過時間屬性和估計時間.暫停是另一個可能實現的功能.使用 QMetaObject::invokeMethod() 允許事件循環定期處理用戶事件,以便您可以取消和更新從 0 到 1 的進度.您也可以輕松調整它以移動文件.

I'm dealing with very large files, in excess of hundreds of GB in size. The User needs to be able to move these files between disks and is on a restricted system with no default file manager. It's possible for the User to realize they've made a mistake and cancel the operation, and as far as I can tell the User will have to wait for the current copy or rename operation to complete. This can leave them feeling frustrated as they wait potentially minutes, only to see that their many GB file still copied. In the case of Copy I could delete the second file, but in the case of rename, which I'm using to move files, I'd have to repeat the operation in reverse to undo it, and that's simply not acceptable.

Is there some way to interrupt copy() and rename() that I'm not seeing in the documentation for QFile, or will I need to put together my own class to handle copy and rename?

解決方案

I don't think the file size has any effect on how long a renaming will take.

For the copy - Qt offers nothing built in, you have to implement it yourself. The key gotcha here is that you will have to find some way to poll for a copy cancellation continuously. This means you cannot lock the main thread in order to be able to process events.

Whether you go for an extra thread in order to keep the main thread responsive, or decide to use the main thread - in both cases you will need to implement "fragmented" copying - one chunk at a time using a buffer, until the file is copied or copying is cancelled. You need this to be able to process user events and track copying progress.

I suggest you implement a QObject derived copy helper worker class which tracks file name, total size, buffer size, progress and clean up on cancellation. Then it is a matter of choice whether you will use it in the main thread or in a dedicated thread.

EDIT: Found it, but you better double check it, since it was done as an example and has not been thoroughly tested:

class CopyHelper : public QObject {
    Q_OBJECT
    Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
public:
    CopyHelper(QString sPath, QString dPath, quint64 bSize = 1024 * 1024) :
        isCancelled(false), bufferSize(bSize), prog(0.0), source(sPath), destination(dPath), position(0) { }
    ~CopyHelper() { free(buff); }

    qreal progress() const { return prog; }
    void setProgress(qreal p) {
        if (p != prog) {
            prog = p;
            emit progressChanged();
        }
    }

public slots:
    void begin() {
        if (!source.open(QIODevice::ReadOnly)) {
            qDebug() << "could not open source, aborting";
            emit done();
            return;
        }
        fileSize = source.size();
        if (!destination.open(QIODevice::WriteOnly)) {
            qDebug() << "could not open destination, aborting";
            // maybe check for overwriting and ask to proceed
            emit done();
            return;
        }
        if (!destination.resize(fileSize)) {
            qDebug() << "could not resize, aborting";
            emit done();
            return;
        }
        buff = (char*)malloc(bufferSize);
        if (!buff) {
            qDebug() << "could not allocate buffer, aborting";
            emit done();
            return;
        }
        QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection);
        //timer.start();
    }
    void step() {
        if (!isCancelled) {
            if (position < fileSize) {
                quint64 chunk = fileSize - position;
                quint64 l = chunk > bufferSize ? bufferSize : chunk;
                source.read(buff, l);
                destination.write(buff, l);
                position += l;
                source.seek(position);
                destination.seek(position);
                setProgress((qreal)position / fileSize);
                //std::this_thread::sleep_for(std::chrono::milliseconds(100)); // for testing
                QMetaObject::invokeMethod(this, "step", Qt::QueuedConnection);
            } else {
                //qDebug() << timer.elapsed();
                emit done();
                return;
            }
        } else {
            if (!destination.remove()) qDebug() << "delete failed";
            emit done();
        }
    }
    void cancel() { isCancelled = true; }

signals:
    void progressChanged();
    void done();

private:
    bool isCancelled;
    quint64 bufferSize;
    qreal prog;
    QFile source, destination;
    quint64 fileSize, position;
    char * buff;
    //QElapsedTimer timer;
};

The done() signal is used to deleteLater() the copy helper / close copy dialog or whatever. You can enable the elapsed timer and use it to implement an elapsed time property and estimated time as well. Pausing is another possible feature to implement. Using QMetaObject::invokeMethod() allows the event loop to periodically process user events so you can cancel and update progress, which goes from 0 to 1. You can easily tweak it for moving files as well.

這篇關于非阻塞工作者 - 中斷文件復制的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數據?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環: for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環?)
Reusing thread in loop c++(在循環 C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環形?)
主站蜘蛛池模板: 日日淫| 国产日韩一区二区三区 | 精品国产欧美一区二区 | 一区二区久久 | 精品视频久久久久久 | 中文字幕第二十页 | 精品在线一区二区 | 国产成人精品a视频一区www | 午夜久久久久久久久久一区二区 | 久久91av | 97久久精品午夜一区二区 | av午夜电影 | 久久久精 | 欧美色综合网 | 国产精品久久久亚洲 | 亚洲精品在线免费观看视频 | 影音先锋亚洲资源 | 99免费在线视频 | 久久久久久久久久久久久久av | 欧美三级成人理伦 | 国产中文 | 91久久国产综合久久 | 一区二区三区网站 | 日韩综合网 | 日屁网站 | 久久久久久久久久久成人 | 亚洲国产成人精品女人久久久野战 | 久久精片 | 国产精品久久久久久久免费大片 | 亚洲精品乱码久久久久久蜜桃 | 日韩高清中文字幕 | 中国黄色毛片视频 | 免费同性女女aaa免费网站 | 91精品国产91久久久久久最新 | 久久久久久国产精品免费免费狐狸 | 懂色中文一区二区在线播放 | 国产成人短视频在线观看 | 成人在线视频观看 | 最新国产精品 | www.国产精品 | 香蕉久久a毛片 |