期望值
異步
異步(Asynchronous)指的是在程序執(zhí)行過程中,某個操作可以獨(dú)立于主線程進(jìn)行。異步操作可以在后臺執(zhí)行,不阻塞主線程,從而提高系統(tǒng)的并發(fā)性和響應(yīng)性。異步編程通過使用回調(diào)函數(shù)、事件驅(qū)動或者協(xié)程等機(jī)制,允許程序在等待某個操作完成的同時,繼續(xù)執(zhí)行其他任務(wù)。異步操作通常會在后臺線程中執(zhí)行,主線程不需要等待操作完成,而是通過回調(diào)函數(shù)或其他方式獲取操作結(jié)果。
C++中,可以使用std::async啟動一個異步任務(wù),它會返回一個std::future對象(期望值),這個對象持有任務(wù)的結(jié)果,當(dāng)需要這個值時,只需要調(diào)用這個對象的get成員函數(shù)。
Case?:

std::async允許靈活地傳入?yún)?shù)。如果第一個參數(shù)是一個指向成員函數(shù)的指針,那么第二個參數(shù)需要提供這個成員函數(shù)所屬的類的具體對象——這個對象可以通過指針傳遞,也可以通過std::ref包裝后傳遞,剩余的參數(shù)則將作為成員函數(shù)的參數(shù)傳入。如果第一個參數(shù)不是指向成員函數(shù)的指針,那么之后的參數(shù)都將作為函數(shù)的參數(shù)傳遞。
Case?:

std::async還可以接收一個額外參數(shù)(如果有的話,作為第一個參數(shù)傳入)——std::launch::async或std::launch::deferred。std::launch::defered表明函數(shù)調(diào)用被延遲到wait或get函數(shù)調(diào)用時才執(zhí)行,std::launch::async表明函數(shù)必須在其所在的獨(dú)立線程上執(zhí)行,?std::launch::deferred | std::launch::async表明實現(xiàn)可以選擇這兩種方式的一種(默認(rèn))。
任務(wù)與期望值的綁定
std::packaged_task用于封裝一個可調(diào)用對象。因為std::packaged_task封裝了一個可調(diào)用對象,它本身可以被調(diào)用,所以可以傳遞到std::thread對象中,或作為可調(diào)用對象傳遞到另一個函數(shù)中,或可以直接進(jìn)行調(diào)用。當(dāng)std::packaged_task作為一個函數(shù)被調(diào)用時,其返回值作為異步結(jié)果存儲在std::future中,可通過get_future獲取。
Case 1?:

Case 2?:

執(zhí)行一個圖形界面線程
在傳統(tǒng)的多線程編程模型中,如果一個線程需要更新圖形界面,它通常需要向特定的圖形界面線程發(fā)送自定義消息或執(zhí)行一些復(fù)雜的同步操作,以確保界面更新的正確性和線程安全性。但是,使用packaged_task可以簡化這個過程。
通過將更新圖形界面的任務(wù)封裝在packaged_task對象中,可以直接將該任務(wù)提交給圖形界面線程執(zhí)行,而無需手動發(fā)送自定義消息。

這段代碼展示了如何使用packaged_task在圖形界面線程中執(zhí)行任務(wù)。gui_thread是圖形界面線程的入口函數(shù)。在這個函數(shù)中,首先調(diào)用process_message處理消息,然后在互斥鎖的保護(hù)下訪問任務(wù)隊列。如果任務(wù)隊列為空,就繼續(xù)下一輪循環(huán)。否則,將任務(wù)隊列的頭部任務(wù)移動到局部變量task中,并從任務(wù)隊列中移除該任務(wù)。最后,調(diào)用task執(zhí)行任務(wù)。
post_task_for_gui_thread用于向圖形界面線程提交任務(wù)。它接受一個可調(diào)用對象作為參數(shù),并創(chuàng)建一個packaged_task對象來封裝該任務(wù)。然后通過get_future獲取任務(wù)的結(jié)果。接著在互斥鎖的保護(hù)下,將任務(wù)加入任務(wù)隊列,并返回任務(wù)的future對象。