c++如何实现文件的异步拷贝功能_不阻塞UI主线程【技巧】

风萱君_2184

风萱君_2184

2026-04-08

168人浏览

原创

std::filesystem::copy 不能直接用于异步拷贝,因其同步阻塞且无进度回调;应改用 std::jthread 分块读写+sleep让权,并通过线程安全机制通知UI更新进度。

c++如何实现文件的异步拷贝功能_不阻塞ui主线程【技巧】

为什么不能直接用 std::filesystem::copy 做异步拷贝

因为 std::filesystem::copy 是同步阻塞的,哪怕你把它丢进 std::thread 或 std::async,底层 read/write 依然会阻塞线程,尤其在大文件、慢存储(如机械硬盘、网络挂载盘)上,线程可能长时间卡在系统调用里,导致线程池饥饿或响应延迟。更关键的是:它不提供进度回调,UI 线程没法实时更新进度条。

用 std::jthread + 分块读写 + std::chrono::milliseconds 控制节奏

核心思路是手动分块搬运数据,并在每块之间主动让出控制权,避免单次系统调用耗时过长。这不是“操作系统级异步 I/O”,但对 UI 友好、可中断、可报告进度。

  • 每次只读 8192 字节(可调),用 std::vector buffer(8192) 避免反复分配
  • 用 std::ifstream 和 std::ofstream 的 read()/write(),它们支持二进制流且不依赖 locale
  • 每写完一块后调用 std::this_thread::sleep_for(std::chrono::milliseconds(1)),给 UI 线程留出调度机会(实测 1ms 足够,太小没意义,太大卡顿)
  • 必须检查 ifs.gcount(),不是所有 read 都能读满;ofs.write() 后也要检查 !ofs

示例片段:

std::jthread copy_thread([&](std::stop_token stoken) {
    std::ifstream ifs(src, std::ios::binary);
    std::ofstream ofs(dst, std::ios::binary);
    std::vector<char> buf(8192);
    while (ifs && !stoken.stop_requested()) {
        ifs.read(buf.data(), buf.size());
        auto n = ifs.gcount();
        if (n > 0) {
            ofs.write(buf.data(), n);
            if (!ofs) break;
            // 更新进度:n 已写入
            progress_callback(static_cast<size_t>(n));
        } else if (ifs.eof()) {
            break;
        }
        std::this_thread::sleep_for(1ms); // 关键:让 UI 线程呼吸
    }
});</size_t></char>

如何安全通知 UI 线程更新进度

不能在工作线程里直接调用 Qt 的 QWidget::update() 或 Win32 的 InvalidateRect() —— 多数 GUI 框架要求 UI 操作必须在主线程执行。最轻量的做法是用线程安全队列 + 主循环轮询,或借助框架原生机制:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • Qt 场景:用 QMetaObject::invokeMethod(..., Qt::QueuedConnection) 投递信号
  • Win32:用 PostMessage() 发自定义消息,主线程 GetMessage() 处理
  • 跨平台裸 C++:用 std::atomic_flag + std::queue + std::mutex 缓存进度值,UI 线程每帧 try_pop()

注意:回调函数本身不能持有长生命周期锁,否则会拖慢工作线程。

Windows 上真异步 I/O 的代价与取舍

若真要使用 CreateFile + ReadFileEx + WriteFileEx(IOCP),需面对:文件句柄必须带 FILE_FLAG_OVERLAPPED,缓冲区必须页对齐(_aligned_malloc),且每个操作需维护 OVERLAPPED 结构体和完成例程。实际收益有限:现代 SSD 下,分块同步读写 + 1ms 让渡已足够流畅;而 IOCP 在小文件场景反而因上下文切换开销更大。除非你在做专业备份工具或处理 TB 级 NAS 文件流,否则没必要。

真正容易被忽略的是错误恢复:断电、磁盘拔出、权限突变都会让 read() 返回 0 或抛异常,工作线程必须捕获 std::filesystem::filesystem_error 并通过 stop_token 优雅退出,否则 std::jthread 析构时会调用 std::terminate。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
C++ Qt图形开发
C++ Qt图形开发

本专题专注于 C++ Qt框架在图形界面开发中的应用,系统讲解窗口设计、信号与槽机制、界面布局、事件处理、数据库连接与跨平台打包等核心技能,通过多个桌面应用项目实战,帮助学员快速掌握 Qt 框架并独立完成跨平台GUI软件的开发。

2025.08.15

5782

7

C++桌面程序开发
C++桌面程序开发

本专题聚焦 C++ 在桌面端图形界面应用开发中的实战应用,系统讲解 Qt 框架的信号与槽机制、界面布局管理、事件响应、数据交互、样式美化与多窗口应用设计等核心知识。通过实战案例(如记事本应用、数据管理工具、系统监控面板),帮助学习者掌握 从UI设计到完整桌面软件开发的C++工程化能力。

2025.10.23

1514

13

C++ 图形界面开发基础(Qt方向)
C++ 图形界面开发基础(Qt方向)

本专题系统讲解 使用 C++ 与 Qt 进行图形界面(GUI)开发的核心技能,内容涵盖 Qt 项目结构、窗口组件、信号与槽机制、事件处理、布局管理、资源管理,以及跨平台编译与打包流程。通过多个小型桌面应用实战案例,帮助学习者掌握从界面设计到功能实现的完整 GUI 开发能力。

2025.12.05

1441

15

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

2025.06.09

5234

18

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

2025.07.04

5411

25

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

2023.08.10

4678

6

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

2025.12.01

583

16

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.26

3419

3

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.27

2978

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习