程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 同步並發操作之等待一次性事件

同步並發操作之等待一次性事件

編輯:C++入門知識

同步並發操作之等待一次性事件


有時候需要用一些後台線程來完成計算,這些計算往往都是一次性的,線程計算完後便結束。這時候可以使用條件變量,但是有點浪費,我們只需要獲取一次結果。C++標准庫中有頭文件,很形象“未來”,獲取未來計算的結果。

使用std::async來啟動一個異步任務。用std::future對象來存儲異步任務返回的結果,這個對象存儲結果。當我們需要結果時,只需調用get()方法。這時如果還沒計算完畢,當前線程會阻塞。

#include
#include


int find_the_answer_to_ltuae();
void do_other_sutff();
int main()
{
	std::future the_answer = std::async(find_the_answer_to_ltuae);
	do_other_sutff();
	std::cout << "The answer is " << the_answer.get() << std::endl;
	return 0;
}
int find_the_answer_to_ltuae()
{

	return 10;
}
void do_other_sutff()
{
	std::cout << "do_other_sutff " << std::endl;
}


可以像線程那樣,向函數傳遞參數

#include
#include
#include

struct X
{
	void foo(int, std::string const&);
	std::string bar(std::string const&);
};
X x;
auto f1 = std::async(&X::foo, &x, 32, "hello");//p->foo(42,"hello")。p是&x
auto f2 = std::async(&X::bar, x, "goodbye");//tmp.bar("goodbye")。x是tmp

struct Y
{
	double operator()(double);
};
Y y;
auto f3 = std::async(Y(), 3.141);//tem(3.141),tmp是Y()的move-constructed
auto f4 = std::async(std::ref(y), 2.718);//y(2.718)
X baz(X&);
std::async(baz, std::ref(x));//調用baz
class move_only
{
public:
	move_only();
	move_only(move_only&&);
	move_only(move_only const&) = delete;
	move_only& operator=(move_only&&);
	move_only& operator=(move_only const&)=delete;
	void operator()();
};
auto f5 = std::async(move_only());//構造臨時對象執行


可以通過傳遞參數來決定是否啟動新的線程或何時啟動新線程,

auto f6 = std::async(std::launch::async, Y(), 1.2);//啟動新線程執行
auto f7 = std::async(std::launch::deferred, baz, std::ref(x));//調用wait或get後才執行
auto f8 = std::async(
	std::launch::deferred | std::launch::async,
	baz, std::ref(x));//由實現來選擇
auto f9 = std::async(baz, std::ref(x));
f7.wait();//執行f7對應的後台線程

結合task和future

可以使用std::packaged_task<>和future結合。當激活std::package_task<>時,調用future的函數。函數返回結果存在關聯的數據中。 std::package_task<>的參數是函數簽名(像函數指針定義)。例如,void()表示無返回值,無參數的函數;int (std::sgring&,double*)表示函數返回類型為int,參數為string引用和double類型指針。當定義std::package_task<>對象時,必須給出參數和返回類型。 std::future<>的返回類型通過成員函數get_future()獲得。 在許多GUI框架中,要求從特定的線程更新GUI。如果一個線程想要更新GUI,它必須給GUI線程發送一個消息。可以通過std::package_task來解決這個問題。
#include
#include
#include
#include
#include

std::mutex m;
std::deque > tasks;
	
bool gui_shutdown_message_received();
void get_and_process_gui_message();

void gui_thread()//GUI線程
{
	while(!gui_shutdown_message_received())//收到GUI關閉信息
	{
		get_and_process_gui_message();//處理GUI窗口信息
		std::packaged_task task;//定義任務
		{
			std::lock_guard lk(m);
			if(tesks.empty())//任務隊列無任務時,執行task()
				continue;
			task=std::move(tasks.front());
			tasks.pop_front();//任務出列
		}
		task();//執行task
	}
}

std::thread gui_bg_thread(gui_thread);
template
std::future post_task_for_gui_thread(Func f)
{
	std::package_task task(f);//創建task
	std::future res=task.get_future();
	std::lock_guard lk(m);
	tasks.push_back(std::move(task));//把task放到隊列
	return res;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved