zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Ubuntu杂记——Ubuntu自带拼音输入发杂乱不堪
    数据库随笔——数据库设计原则(转)
    Java学习笔记——回调函数
    Android随笔之——静默安装、卸载
    Hibernate学习之——搭建log4j日志环境
    Hibernate学习之——Hibernate环境搭建
    Android随笔之——闹钟制作铺垫之AlarmManager详解
    Android随笔之——Android时间、日期相关类和方法
    Nyoj 天下第一(spfa)
    hdu 最大三角形(凸包+旋转卡壳)
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/12055751.html
Copyright © 2011-2022 走看看