C 异步编程前置准备编译器GCC 7 / Clang 5 / MSVC 2017编译时需链接线程库-pthreadLinux/Mac或无需额外参数Windows MSVC例子1std::async std::future 异步计算阶乘C11适用场景快速启动异步任务主线程继续执行其他逻辑最后获取异步结果如异步计算、异步IO模拟。核心原理std::async自动创建线程执行任务返回std::futurestd::future异步结果的“提货单”调用get()获取结果会阻塞直到结果就绪完整代码#includeiostream#includefuture#includechrono#includethreadusingnamespacestd;// 耗时任务计算n的阶乘模拟3秒耗时longlongcalculateFactorial(intn){cout[Async Thread] Starting factorial calculation, n nendl;// 模拟耗时操作3秒this_thread::sleep_for(chrono::seconds(3));longlongresult1;for(inti1;in;i){result*i;}cout[Async Thread] Calculation finished, result resultendl;returnresult;}intmain(){cout[Main Thread] Program startedendl;// ✨ 关键1启动异步任务std::launch::async 强制立即创建新线程futurelonglongfutasync(launch::async,calculateFactorial,10);// 主线程继续做其他事不阻塞cout[Main Thread] Continuing other logic (simulating 1s delay)endl;this_thread::sleep_for(chrono::seconds(1));// ✨ 关键2获取异步结果如果任务没做完这里会阻塞等待cout[Main Thread] Preparing to get async result...endl;longlongfinalResultfut.get();cout[Main Thread] Final result: finalResultendl;cout[Main Thread] Program endedendl;return0;}编译与运行# 编译C11及以上g-stdc17 async_factorial.cpp-oasync_factorial-pthread# 运行./async_factorial运行结果[Main Thread] Program started [Async Thread] Starting factorial calculation, n 10 [Main Thread] Continuing other logic (simulating 1s delay) [Main Thread] Preparing to get async result... [Async Thread] Calculation finished, result 3628800 [Main Thread] Final result: 3628800 [Main Thread] Program ended关键知识点std::launch启动策略launch::async强制立即创建新线程执行任务最常用launch::deferred延迟执行直到调用future.get()时才在当前线程运行不推荐future.get()注意事项只能调用一次调用后future会失效如果异步任务没做完get()会阻塞等待直到结果就绪线程安全std::async自动管理线程生命周期无需手动join()例子2std::promise std::future 跨线程传递结果C11适用场景需要手动控制异步结果的设置时机如在一个线程中计算另一个线程中设置结果或者跨线程传递异常。核心原理std::promise生产者负责设置异步结果或异常std::future消费者负责获取结果两者通过promise.get_future()配对完整代码#includeiostream#includefuture#includethread#includestdexceptusingnamespacestd;// 线程函数接收promise引用计算斐波那契数列第n项voidcalculateFibonacci(intn,promiselonglongprom){cout[Calculation Thread] Starting Fibonacci calculation for term nendl;try{if(n0){throwinvalid_argument(n cannot be negative);}longlonga0,b1;for(inti2;in;i){longlongnextab;ab;bnext;}// ✨ 关键1设置结果到promiseprom.set_value(b);cout[Calculation Thread] Result setendl;}catch(...){// ✨ 关键2如果出错设置异常到promiseprom.set_exception(current_exception());}}intmain(){cout[Main Thread] Program startedendl;// 1. 创建promise生产者promiselonglongprom;// 2. 从promise获取future消费者futurelonglongfutprom.get_future();// 3. 启动计算线程把promise传进去注意用ref()传递引用threadt(calculateFibonacci,20,ref(prom));// 主线程继续做别的事cout[Main Thread] Continuing other logic (simulating 1s delay)endl;this_thread::sleep_for(chrono::seconds(1));// 4. 获取结果如果有异常get()会抛出try{cout[Main Thread] Preparing to get async result...endl;longlongresultfut.get();cout[Main Thread] Fibonacci term 20: resultendl;}catch(constexceptione){cout[Main Thread] Exception: e.what()endl;}// 必须join线程否则会崩溃t.join();cout[Main Thread] Program endedendl;return0;}编译与运行# 编译g-stdc17 promise_future.cpp-opromise_future-pthread# 运行./promise_future运行结果[Main Thread] Program started [Calculation Thread] Starting Fibonacci calculation for term 20 [Main Thread] Continuing other logic (simulating 1s delay) [Calculation Thread] Result set [Main Thread] Preparing to get async result... [Main Thread] Fibonacci term 20: 6765 [Main Thread] Program ended关键知识点promise只能设置一次结果set_value()或set_exception()只能调用一次多次调用会崩溃传递引用必须用std::ref()thread构造函数默认拷贝参数传递引用必须显式用ref()异常传递用set_exception()把异常传给futurefuture.get()会在主线程抛出异常例子3std::packaged_task 打包任务延迟执行C11适用场景需要把任务打包成可调用对象延迟执行比如把任务放进队列后面再调度执行或者把任务传给线程池。核心原理std::packaged_task把可调用对象函数、Lambda、仿函数打包内部绑定了一个future调用packaged_task()执行任务自动把结果设置到内部future完整代码#includeiostream#includefuture#includethread#includevectorusingnamespacestd;// 任务函数计算1到n的平方和intcalculateSquareSum(intn){cout[Task Thread] Starting square sum calculation from 1 to nendl;this_thread::sleep_for(chrono::seconds(2));// 模拟耗时intsum0;for(inti1;in;i){sumi*i;}cout[Task Thread] Calculation finishedendl;returnsum;}intmain(){cout[Main Thread] Program startedendl;// 1. 把函数打包成packaged_taskpackaged_taskint(int)task(calculateSquareSum);// 2. 从packaged_task获取futurefutureintfuttask.get_future();// 3. 延迟执行把任务放进线程模拟调度cout[Main Thread] Task packaged, preparing for deferred execution...endl;threadt(move(task),5);// packaged_task不可拷贝必须用move()转移所有权// 主线程继续做别的事cout[Main Thread] Continuing other logic (simulating 1s delay)endl;this_thread::sleep_for(chrono::seconds(1));// 4. 获取结果cout[Main Thread] Preparing to get async result...endl;intresultfut.get();cout[Main Thread] Square sum from 1 to 5: resultendl;t.join();cout[Main Thread] Program endedendl;return0;}编译与运行# 编译g-stdc17 packaged_task.cpp-opackaged_task-pthread# 运行./packaged_task运行结果[Main Thread] Program started [Main Thread] Task packaged, preparing for deferred execution... [Task Thread] Starting square sum calculation from 1 to 5 [Main Thread] Continuing other logic (simulating 1s delay) [Main Thread] Preparing to get async result... [Task Thread] Calculation finished [Main Thread] Square sum from 1 to 5: 55 [Main Thread] Program ended关键知识点packaged_task不可拷贝只能移动必须用std::move()转移所有权给线程或其他对象延迟执行打包后可以先存起来后面再调用task()执行比如放进任务队列适用场景线程池、任务调度器、需要把任务和future绑定的场景例子4C20协程 异步等待现代C趋势适用场景用同步代码的写法写异步逻辑彻底告别回调地狱比如异步IO、网络请求、UI交互。前置条件编译器支持C20GCC 10、Clang 13、MSVC 2019核心原理C20协程靠三个关键字实现关键字作用co_await暂停协程等待异步操作完成co_return协程结束返回结果co_yield暂停协程返回一个值生成器用完整代码#includeiostream#includecoroutine#includechrono#includethread#includeexceptionusingnamespacestd;// ✨ 关键1定义协程返回类型 TaskTtemplatetypenameTstructTask{// 协程承诺类型必须定义协程的核心structpromise_type{T result;exception_ptr exception;suspend_neverinitial_suspend(){return{};}suspend_neverfinal_suspend()noexcept{return{};}voidreturn_value(T value){resultvalue;}voidunhandled_exception(){exceptioncurrent_exception();}Taskget_return_object(){returnTask{coroutine_handlepromise_type::from_promise(*this)};}};coroutine_handlepromise_typehandle;// 协程句柄Task(coroutine_handlepromise_typeh):handle(h){}~Task(){if(handle)handle.destroy();}// 获取结果Tget(){if(!handle.done())handle.resume();if(handle.promise().exception){rethrow_exception(handle.promise().exception);}returnhandle.promise().result;}};// ✨ 关键2定义可等待对象 DelayAwaiter异步等待指定时间structDelayAwaiter{chrono::milliseconds duration;DelayAwaiter(chrono::milliseconds d):duration(d){}// 1. 检查是否已经就绪这里我们要等待所以返回falseboolawait_ready()constnoexcept{returnfalse;}// 2. 协程暂停时调用在这里启动异步等待voidawait_suspend(coroutine_handlehandle)const{// 启动一个新线程等待指定时间后恢复协程thread({this_thread::sleep_for(duration);handle.resume();// 恢复协程执行}).detach();}// 3. 协程恢复时调用返回结果这里没有结果返回voidvoidawait_resume()constnoexcept{}};// 辅助函数创建DelayAwaiterDelayAwaiterdelay(chrono::milliseconds d){returnDelayAwaiter(d);}// ✨ 关键3写协程函数用co_await和co_returnTaskstringasyncGreet(){cout[Coroutine] Started executionendl;// 暂停协程等待1秒co_awaitdelay(chrono::seconds(1));cout[Coroutine] Resumed executionendl;// 返回结果co_returnHello from C20 Coroutine!;}intmain(){cout[Main Thread] Program startedendl;// 调用协程获取Task对象TaskstringtaskasyncGreet();// 主线程继续做别的事cout[Main Thread] Continuing other logic (simulating 500ms delay)endl;this_thread::sleep_for(chrono::milliseconds(500));// 获取协程结果cout[Main Thread] Preparing to get coroutine result...endl;string resulttask.get();cout[Main Thread] Coroutine result: resultendl;cout[Main Thread] Program endedendl;return0;}编译与运行# 必须用C20g-stdc20 coroutine_async.cpp-ocoroutine_async-pthread# 运行./coroutine_async运行结果[Main Thread] Program started [Coroutine] Started execution [Main Thread] Continuing other logic (simulating 500ms delay) [Coroutine] Resumed execution [Main Thread] Preparing to get coroutine result... [Main Thread] Coroutine result: Hello from C20 Coroutine! [Main Thread] Program ended关键知识点协程的核心是“暂停-恢复”co_await暂停协程让出CPU给主线程异步操作完成后handle.resume()恢复协程执行协程比回调更清晰用同步代码的逻辑写异步没有嵌套回调可读性极强生产环境建议用库自定义协程返回类型比较复杂生产环境推荐用cppcoro、libuv或ASIO等成熟库总结4种方式怎么选方式复杂度适用场景推荐指数std::async⭐ 简单快速启动异步任务无需手动管理线程⭐⭐⭐⭐⭐std::promise⭐⭐ 中等需要手动控制结果设置时机跨线程传递异常⭐⭐⭐⭐std::packaged_task⭐⭐ 中等打包任务延迟执行线程池/任务调度⭐⭐⭐⭐C20协程⭐⭐⭐⭐ 复杂大规模异步逻辑避免回调地狱现代C趋势⭐⭐⭐⭐⭐