查看完整版本: [-- 多线程调用CopyFileEx拷贝大文件(超过1GB的文件)回调函数100%时,等一分钟左右才返回CopyFileEx的返回值 --]

QTCN开发网 -> Qt基础编程 -> 多线程调用CopyFileEx拷贝大文件(超过1GB的文件)回调函数100%时,等一分钟左右才返回CopyFileEx的返回值 [打印本页] 登录 -> 注册 -> 回复主题 -> 发表主题

lwei24 2021-08-20 10:26

多线程调用CopyFileEx拷贝大文件(超过1GB的文件)回调函数100%时,等一分钟左右才返回CopyFileEx的返回值

各位大佬,请帮帮忙,如下代码,在多线程调用CopyFileEx拷贝大文件(超过1GB的文件)回调函数的拷贝进度值到达100%时,为什么没有立即返回CopyFileEx的返回值,而是等一分钟左右才返回CopyFileEx的返回值,导致了主线程一直在等子线程,出现了界面假死的情况。欢迎各位大佬指点一下,小弟在此不胜感激了!
  1. BOOL bRet = CopyFileEx((LPCWSTR)src,(LPCWSTR)dst, CallBackCopyProgressFunc, this, (LPBOOL)m_bCancel, COPY_FILE_FAIL_IF_EXISTS);
        qWarning()<<"endTime="<<QTime::currentTime().toString("h:m:s");
        qWarning()<<"ret="<<bRet;
        if(!bRet)
        {
            QFile fileTmp(dstPath);
            fileTmp.remove();
            qWarning()<<QString("CopyFile Failed, ErrorCode=%1!").arg(QString::number(GetLastError()));
            return;
        }
        else
        {
            qWarning()<<QString("CopyFile Success!");
        }
        return;


回调函数:
  1. static DWORD CALLBACK CallBackCopyProgressFunc(LARGE_INTEGER totalSize,  LARGE_INTEGER totalTransferred, LARGE_INTEGER streamSize,
                                            LARGE_INTEGER streamTransferred, DWORD streamNo,DWORD callbackReason,HANDLE src,HANDLE dst,LPVOID data)
    {
        Q_UNUSED(streamSize) Q_UNUSED(streamTransferred)
                Q_UNUSED(streamNo) Q_UNUSED(callbackReason)
                Q_UNUSED(src) Q_UNUSED(dst)

        static int nRecord = 0;
        nRecord++;

        auto pObject =static_cast<subThread *>(data);
        if(totalSize.QuadPart != 0)
        {
            pObject->m_nCopyValue = totalTransferred.QuadPart*100/totalSize.QuadPart;
            if(pObject->m_nCopyValue != 0 && pObject->m_nCopyValue%50 == 0)
                qWarning()<<QString("emit Number of callbacks:%1,The copy progress of value:%2").arg(QString::number(nRecord)).arg(QString::number(pObject->m_nCopyValue));
            if(pObject->m_nCopyValue > 0)
            {
                emit pObject->sigCopyValue(pObject->m_nCopyValue);
                qApp->processEvents();
                if(pObject->m_nCopyValue == 100)
                {
                    pObject->m_bCancel = TRUE;
                }
            }
        }

        return PROGRESS_CONTINUE;
    }










hitler++ 2021-08-21 20:28
如果不是用的固态硬盘,任何涉及磁盘操作用多线程只会导致速度更慢,除非系统已经缓存过数据了,否则多个线程抢占物理磁头,IOPS一共才20多,(100%时还在等待,应该是系统还在flush数据到硬盘)

snow_man_0 2021-08-23 07:59
可以自己写一个CopyFileEx函数,不用别人的

lwei24 2021-08-25 11:13
hitler++:如果不是用的固态硬盘,任何涉及磁盘操作用多线程只会导致速度更慢,除非系统已经缓存过数据了,否则多个线程抢占物理磁头,IOPS一共才20多,(100%时还在等待,应该是系统还在flush数据到硬盘)
 (2021-08-21 20:28) 

请问有什么办法可以优化吗?

lwei24 2021-08-25 11:20
snow_man_0:可以自己写一个CopyFileEx函数,不用别人的 (2021-08-23 07:59) 

bool copyFileA(QString &srcPath, QString &dstPath)
{
    QFile file(srcPath);
    qWarning()<<"file size="<<file.size();

    QByteArray s = srcPath.toLatin1();
    char *src = (char*)s.data();

    QByteArray d = dstPath.toLatin1();
    char *dst = (char*)d.data();

    ifstream in(src, ios::binary);
    ofstream ou(dst, ios::binary);

    if(!in.is_open())
    {
        qWarning()<<"src is open failed!";
        emit sigCopyValue(m_nCopyValue);
        return false;
    }

    if(dst == src)
    {
        qWarning()<<"the src file can't be same with dst file";
        emit sigCopyValue(m_nCopyValue);
        return false;
    }

    char buffer[64*1024] = {0};
    long long totalBytes = 0;
    qWarning()<<"hello...";
    //m_mutex2.lock();
    while(in)
    {
        in.read(buffer, 64*1024);
        ou.write(buffer, in.gcount());

        totalBytes += in.gcount();
        m_nCopyValue = (int)((totalBytes*1.0/file.size())*100);
        qWarning()<<"copyValue="<<m_nCopyValue;
        QElapsedTimer et;
        et.start();
        while(et.elapsed() < 25)
        {
            emit sigCopyValue(m_nCopyValue);
            QCoreApplication::processEvents();
        }
        if(totalBytes == file.size())
            break;
    }
    //m_mutex2.unlock();
    in.close();
    ou.close();

    qWarning()<<"fstream close";
    return true;
}

我自己也写了一个类似CopyFileEx的函数,但是在同时启动两个线程去拷贝两个大于1GB的文件时,它直接进入那个循环,然后就不停的发信号,可能是发信号太快了,主线程没有来的及回复,导致了主界面还是会卡顿、假死,请问以上的代码,可以做哪些优化或修改吗?

snow_man_0 2021-08-28 03:18
lwei24:bool copyFileA(QString &srcPath, QString &dstPath)
{
    QFile file(srcPath);
    qWarning()<<"file size="<<file.size();
....... (2021-08-25 11:20) 

void copyFileA(const QString &srcPath, const QString &dstPath, int* progress)
后面加上进度

把copyFileA放在单独线程里面,在外面监视progress值,就可以了

函数尽量保持独立,不要在函数里面向外发射信号

另外用QFILE就可以,不需要用IOStream

lwei24 2021-08-30 10:54
snow_man_0:void copyFileA(const QString &srcPath, const QString &dstPath, int* progress)
后面加上进度
把copyFileA放在单独线程里面,在外面监视progress值,就可以了
....... (2021-08-28 03:18) 

你说的外面监视,是要声明一个静态的变量progress吗??如果不是在函数里发送信号,又怎么能够实时获取到进度值呢?

fsu0413 2021-09-04 13:05
我觉得可能就是这样的,因为Windows自带的文件管理器也这样
界面假死的话,看看是不是你的函数并没有跑在子线程

lwei24 2021-09-09 17:36
fsu0413:我觉得可能就是这样的,因为Windows自带的文件管理器也这样
界面假死的话,看看是不是你的函数并没有跑在子线程 (2021-09-04 13:05) 

好的,多谢!


查看完整版本: [-- 多线程调用CopyFileEx拷贝大文件(超过1GB的文件)回调函数100%时,等一分钟左右才返回CopyFileEx的返回值 --] [-- top --]



Powered by phpwind v8.7 Code ©2003-2011 phpwind
Gzip disabled