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;
}

C++在函數定義的時候在后面加上=delete是什么意思例如:RoundRobin(const RoundRobin& rhs) = delete;

即將該函數定義成已刪除的函數,任何試圖調用它的行為將產生編譯期錯誤。是C++11標准的內容。

lk.push_back(std::move(__p)); ,若果不用move的話會報錯

 

 因為future的拷貝構造函數已經被定義為刪除delete函數。所以需要用move轉移控制權。

https://blog.csdn.net/tmxfh/article/details/54799693


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM