【问题标题】:How to get Windows thread pool to call class member function?如何让 Windows 线程池调用类成员函数?
【发布时间】:2011-10-03 17:18:49
【问题描述】:

我希望 Windows 线程池 (QueueUserWorkItem()) 调用我的类的成员函数。

不幸的是,这不能通过将成员函数指针作为参数传递给 QueueUserWorkItem() 来直接完成。

难点在于,多个成员函数必须是可调用的,并且它们具有不同的签名(尽管都返回 void)。

可能需要添加几层抽象才能使其正常工作,但我不确定如何处理。有什么想法吗?

【问题讨论】:

    标签: c++ callback threadpool member-functions


    【解决方案1】:

    这可能会有所帮助。 您可以使用 tr1::function () 和 tr1::bind 来“合并”各种调用:

       #include <iostream>
       #include <tr1/functional>
       using namespace std;
       using namespace tr1;
    
       class A
       {
       public:
          void function(int i) { cout << "Called A::function with i=" << i << endl; }
       };
    
       void different_function(double c) {
           cout << "Called different_function with c=" << c << endl;
       }
    
    
       int main(int argc, char* argv[])
       {
          function<void()> f = bind(different_function, 3.14165);
          f();
    
          A a;
          f = bind(&A::function, a, 10);
          f();
    
          return 0;
       }
    

    函数对象的地址可以作为单个可调用对象传递(只需要一个地址)。

    【讨论】:

    • 太棒了!正是我需要的。惊人的 STL 魔法。谢谢你向我介绍这个。现在唯一的问题是线程安全。当线程池试图使用它时,函数对象很可能已经死了。我想我需要堆构造函数,但要小心内存泄漏。关于如何处理这个问题的任何想法?
    • 是的,你需要在堆上构建它。消费线程可以删除它,但我建议使用 tr1:shared_ptr ()
    【解决方案2】:

    示例: 在您的班级中添加:

    char m_FuncToCall;
    
        static DWORD __stdcall myclass::ThreadStartRoutine(LPVOID myclassref)
        {
          myclass* _val =  (myclass*)myclassref;
          switch(m_FuncToCall)
          {
             case 0:
              _val->StartMyOperation();
             break;
           }
           return 0;
        }
    

    然后创建一个成员以添加到队列中

    void myclass::AddToQueue(char funcId)
     {
        m_FuncToCall=funcId;
       QueueUserWorkItem(ThreadStartRoutine,this,WT_EXECUTEDEFAULT);
     }
    

    或创建

    typedef void (*MY_FUNC)(void);
        typedef struct _ARGUMENT_TO_PASS
        {
         myclass* classref;
         MY_FUNC func;
    
        }ARGUMENT_TO_PASS;
    

    然后

    void myclass::AddToQueue(MY_FUNC func)
    {
       ARGUMENT_TO_PASS _arg;
       _arg.func = func;
       _arg.classref = this;
        QueueUserWorkItem(ThreadStartRoutine,&_arg,WT_EXECUTEDEFAULT);
    }
    

    如果您需要进一步的解释,请随时询问:)

    编辑:您需要更改第二个示例的 ThreadStartRoutine 您还可以更改结构以保存传递的参数

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      • 2012-10-28
      • 1970-01-01
      相关资源
      最近更新 更多