pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

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

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 緩沖區大?。籷real 程序;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 ()?環形?)
主站蜘蛛池模板: 自动化生产线-自动化装配线-直流电机自动化生产线-东莞市慧百自动化有限公司 | 医用酒精_84消毒液_碘伏消毒液等医用消毒液-漓峰消毒官网 | 变位机,焊接变位机,焊接变位器,小型变位机,小型焊接变位机-济南上弘机电设备有限公司 | 生物风-销售载体,基因,质粒,ATCC细胞,ATCC菌株等,欢迎购买-百风生物 | 木材烘干机,木炭烘干机,纸管/佛香烘干设备-河南蓝天机械制造有限公司 | 无菌实验室规划装修设计-一体化实验室承包-北京洁净净化工程建设施工-北京航天科恩实验室装备工程技术有限公司 | 单螺旋速冻机-双螺旋-流态化-隧道式-食品速冻机厂家-广州冰泉制冷 | 定制液氮罐_小型气相液氮罐_自增压液氮罐_班德液氮罐厂家 | 拉力测试机|材料拉伸试验机|电子拉力机价格|万能试验机厂家|苏州皖仪实验仪器有限公司 | 防水接头-电缆防水接头-金属-电缆密封接头-不锈钢电缆接头 | TPE_TPE热塑性弹性体_TPE原料价格_TPE材料厂家-惠州市中塑王塑胶制品公司- 中塑王塑胶制品有限公司 | 断桥铝破碎机_发动机破碎机_杂铝破碎机厂家价格-皓星机械 | 预制围墙_工程预制围墙_天津市瑞通建筑材料有限公司 | 纯化水设备-纯水设备-超纯水设备-[大鹏水处理]纯水设备一站式服务商-东莞市大鹏水处理科技有限公司 | 镀锌钢格栅_热镀锌格栅板_钢格栅板_热镀锌钢格板-安平县昊泽丝网制品有限公司 | 3d打印服务,3d打印汽车,三维扫描,硅胶复模,手板,快速模具,深圳市精速三维打印科技有限公司 | 不锈钢复合板|钛复合板|金属复合板|南钢集团安徽金元素复合材料有限公司-官网 | 缓蚀除垢剂_循环水阻垢剂_反渗透锅炉阻垢剂_有机硫化物-郑州威大水处理材料有限公司 | 护腰带生产厂家_磁石_医用_热压护腰_登山护膝_背姿矫正带_保健护具_医疗护具-衡水港盛 | 武汉高低温试验箱_恒温恒湿试验箱厂家-武汉蓝锐环境科技有限公司 | 博莱特空压机|博莱特-阿特拉斯独资空压机品牌核心代理商 | 上海三信|ph计|酸度计|电导率仪-艾科仪器| 定制异形重型钢格栅板/钢格板_定做踏步板/排水沟盖板_钢格栅板批发厂家-河北圣墨金属制品有限公司 | 电销卡 防封电销卡 不封号电销卡 电话销售卡 白名单电销卡 电销系统 外呼系统 | 臭氧实验装置_实验室臭氧发生器-北京同林臭氧装置网 | 苏州同创电子有限公司 - 四探针测试仪源头厂家| sus630/303cu不锈钢棒,440C/430F/17-4ph不锈钢研磨棒-江苏德镍金属科技有限公司 | 电动葫芦|手拉葫芦|环链电动葫芦|微型电动葫芦-北京市凌鹰起重机械有限公司 | 依维柯自动挡房车,自行式国产改装房车,小型房车价格,中国十大房车品牌_南京拓锐斯特房车 - 南京拓锐斯特房车 | 西安文都考研官网_西安考研辅导班_考研培训机构_西安在职考研培训 | 北京银联移动POS机办理_收银POS机_智能pos机_刷卡机_收银系统_个人POS机-谷骐科技【官网】 | 包装机传感器-搅拌站传感器-山东称重传感器厂家-济南泰钦电气 | 济南电缆桥架|山东桥架-济南航丰实业有限公司 | 一体式钢筋扫描仪-楼板测厚仪-裂缝检测仪-泰仕特(北京) | 电主轴-高速精密电主轴-高速电机厂家-瑞德沃斯品牌有限公司 | 工业胀紧套_万向节联轴器_链条-规格齐全-型号选购-非标订做-厂家批发价格-上海乙谛精密机械有限公司 | 东莞精密模具加工,精密连接器模具零件,自動機零件,冶工具加工-益久精密 | 三价铬_环保铬_环保电镀_东莞共盈新材料贸易有限公司 | 北京软件开发_软件开发公司_北京软件公司-北京宜天信达软件开发公司 | 昆山PCB加工_SMT贴片_PCB抄板_线路板焊接加工-昆山腾宸电子科技有限公司 | 哈尔滨治「失眠/抑郁/焦虑症/精神心理」专科医院排行榜-京科脑康免费咨询 一对一诊疗 |