std::future
std::future是一個非常有用也很有意思的東西,簡單說std::future提供了一種訪問異步操作結果的機制。從字面意思來理解,它表示未來,我覺得這個名字非常貼切,因爲一個異步操作我們是不可能馬上就獲取操作結果的,只能在未來某個時候獲取,但是我們可以以同步等待的方式來獲取結果,可以通過查詢future的狀態(future_status)來獲取異步操作的結果。future_status有三種狀態:
- deferred:異步操作還沒開始
- ready:異步操作已經完成
- timeout:異步操作超時
獲取future結果有三種方式:get、wait、wait_for,其中
- get:等待異步操作結束並返回結果,
- wait:只是等待異步操作完成,沒有返回值,
- wait_for:是超時等待返回結果。
std::async
std::async的原型async(std::launch::async | std::launch::deferred, f, args...),第一個參數是線程的創建策略,有兩種策略,默認的策略是立即創建線程:
- std::launch::async:在調用async就開始創建線程。
- std::launch::deferred:延遲加載方式創建線程。調用async時不創建線程,直到調用了future的get或者wait時才創建線程。
第二個參數是線程函數,第三個參數是線程函數的參數。
#include<iostream>
#include<thread>
#include<string>
#include<vector>
#include<list>
#include<mutex>
#include<future>
using namespace std;
int mythread() //線程入口函數
{
cout << "mythread start" << "threadid= " << std::this_thread::get_id() << endl; //打印線程id
std::chrono::milliseconds dura(5000); //定一個5秒的時間
std::this_thread::sleep_for(dura); //休息一定時常
cout << "mythread end" << "threadid= " << std::this_thread::get_id() << endl;
return 5;
}
int main()
{
cout << "main" << "threadid= " << std::this_thread::get_id() << endl;
std::future<int> result = std::async(std::launch::async, mythread);//std::launch::deferred時進入std::future_status::deferred
cout << "continue....." << endl;
//枚舉類型
std::future_status status = result.wait_for(std::chrono::seconds(10));//等待10秒是ready狀態,1秒是timeout
if (status == std::future_status::deferred)
{
//線程被延遲執行了,系統資源緊張
//cout << result.get() << endl; //此時採取調用mythread()
//result.wait();
}
else if (status == std::future_status::timeout)//
{
//超時:表示線程還沒執行完;我想等待你1秒,希望你返回,你沒有返回,那麼 status = timeout
//線程還沒執行完
cout << "超時:表示線程還沒執行完!" << endl;
}
else if (status == std::future_status::ready)
{
//表示線程成功返回
cout << "線程成功執行完畢,返回!" << endl;
cout << result.get() << endl;
}
cout << "I love China!" << endl;
return 0;
}
void MyTest::testCls()
{
MyCls mydata;
//async(類成員函數, 類對象, 參數1, 參數2,...,返回結果)
std::future<bool> res = std::async(&MyCls::test, &mydata, hoImg, startPos, &rtnResult);
res.wait();
m_cbk(&rtnResult);
}
void MyCls::test(Img hoImg, double startPos, int* rtnResult)
{
......
}