1. 程式人生 > >C++ 11 執行緒呼叫類的成員函式解決辦法

C++ 11 執行緒呼叫類的成員函式解決辦法

在C++中,_beginthreadex 建立執行緒是很麻煩的。要求入口函式必須是類的靜態函式。

通常,可以採用thunk,或者模板來實現。

因C++ 11中引入了 std::async ,可以很好的解決這個問題了。

值得注意的是,在迴圈中 std::async 建立執行緒,我試了好多次總是失敗,後來看老外的程式碼,採用 std::move解決了問題。

具體見實現程式碼。

// ConsoleApplication1.cpp : 定義控制檯應用程式的入口點。

#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <functional>
#include <process.h>
#include <thread>
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>
#include <future>
#include <list>
#include <sstream>
using namespace std;


typedef UINT(WINAPI* THREADPROC)(LPVOID);


class XTest
{
public:
	XTest() {};
	~XTest() {};
	
	UINT XTest::RunLoop(LPVOID obj)
	{
		int count = 0;
		for (int i = 0; i < 5; i++)
		{
			Sleep(100);
			std::ostringstream ostr;
			ostr << "執行緒" << (INT)obj << "   靜態執行次數 [" << count++ << "] -RunLoop- " << std::endl;
			cout << ostr.str().c_str() << std::endl;
		}
		return 0;
	}

	UINT XTest::XFH()
	{
		//  問題就出在這裡,_beginthreadex不能呼叫類的成員函式,須靜態的才行。
		//int rt = _beginthreadex(NULL, 0, (THREADPROC) [this](LPVOID) { return this->RunLoop(0); }, 0, 0, NULL);
		// auto pppp = (&XTest::RunLoop);
		// ULONG_PTR* kkkk = (ULONG_PTR*)&pppp;
		std::list<std::future<UINT> > lk;
		for (int i =0 ; i<8 ; i++)
		{
			//auto __p = std::async(std::launch::async , [this, i]() {return this->RunLoop((LPVOID)i); });
			auto __p = std::async(std::launch::async, &XTest::RunLoop, this, (LPVOID)i);
			// __p.wait(); 不可以呼叫。否則會變成同步了。
			lk.push_back(std::move(__p));  // 這裡必須要用move,否則就會變成同步了。。
			//auto k = std::thread([this , i]() {this->RunLoop((LPVOID)i); });
			//k.detach();
		}
		// 此行程式碼用於等執行緒結束,會阻塞主執行緒。
		for (auto &e : lk)
		{
			e.wait();
		}
		cout << "等執行緒結束" << endl;
		Sleep(1000);
		return 0;
	}
};

int main()
{
	auto mmm = new XTest;
	mmm->XFH();
	cout << "------";
	getchar();
	return 0;
}