使用boost线程和非静态类函数

时间:2011-01-03 01:17:10

标签: c++ multithreading function boost static

所以我做了一些研究,发现你可以通过使用“this”和boost :: bind等来创建一个boost :: thread对象并让它以非静态类函数开始。它真的没有对我来说很有意义,我能找到的所有例子都有boost :: thread对象在与它开始的函数相同的类中启动,因此可以使用它。然而,我在另一个类中启动线程所以我害怕使用“this”,我会说“this”来自我创建线程的类,而不是函数所在的类(我可能错了,我需要更多地了解这个“这个”家伙。以下是我遇到问题的一个例子。

ANNGUI.h

class ANNGUI
{
private:
    boost::thread *GUIThread;
    Main *GUIMain;
public:
    // Creates the entire GUI and all sub-parts.
    int CreateGUI();
}

ANNGUI.cpp

int ANNGUI::CreateGUI()
{
        GUIMain = new Main();
    GUIThread = new boost::thread(GUIMain->MainThreadFunc);
};

这不是全部来源,但我认为我的问题就在这里,我知道我必须以某种方式处理“这个”,但我不确定如何。我可以使用静态函数,但我真的不想让变量变为静态。 感谢。

此外,是否有任何非常好的资源可以使用任何升级库?他们的网站文档似乎很好,但在我的头上。

5 个答案:

答案 0 :(得分:82)

当您创建的函数对象绑定到对象成员函数时,this关键字与boost::bind一起使用。成员函数不能与实例分开存在,因此当使用boost::bind从成员函数创建functor对象时,需要指向实例的指针。这正是this关键字实际上是什么。如果在类的成员函数中使用this关键字,则获得的是指向该类的当前实例的指针。

如果您要从外部调用类成员函数bind,您可能会说:

int main()
{
  Foo f;
  boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, &f));
}

这里,我们使用Foo :: some_function作为我们的线程函数。但我们无法使用this,因为我们正在bind调用main。但如果我们从Foo的成员函数中调用this,可以使用bind来实现同样的目的,如下所示:

void Foo::func1()
{
  boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, this));
}

如果成员函数是静态的,或者只是常规(非成员)函数,那么根本不需要实例指针。你会这样做:

boost::thread* thr = new boost::thread(some_regular_function);

答案 1 :(得分:40)

正如其他人提到的,当你想在新线程中调用对象方法时,你必须提供该对象的地址。但是你不需要调用boost::bind,你可以像这样使用重载的boost::thread构造函数:

GUIThread = new boost::thread(&Main::MainThreadFunc, GUIMain);

如果方法属于同一个类,则使用this获取当前实例的地址,例如:

t = new boost::thread(&myclass::compute, this);

如果方法有参数,您可以在第二个参数后指定它们,例如:

t = new boost::thread(&myclass::compute, this, p1, p2);

答案 2 :(得分:3)

boost :: bind是你的朋友(虽然它有时会有一种粗略的方式显示它)!

使用GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain));

然后使您的MainThreadFunc成为常规成员。这意味着您可以像平常一样直接使用实例变量。

这样的事情:

class GUIMain {
public:
  GUIMain() : m_Member(42) {}

  void MainThreadFunc() {
    // use all members as you would normally do
    std::cout << m_Member << std::endl;
  }

private:
  int m_Member;
};

答案 3 :(得分:3)

在这种情况下,将非静态成员函数视为以this作为第一个参数的自由函数是很有用的,例如在您的void MainThreadFunc(Main* this)案例中。

boost::thread接受一个无效的仿函数,所以你必须传递一个隐含的仿函数,其中包含对实例GUIMain的引用,并调用GUIMain->MainThreadFunc,如上所述,就像MainThreadFunc(GUIMain)一样。

Boost(现在也是带有TR1的C ++)提供了帮助来创建这样的仿函数,即boost::bind(或者boost::lambda::bind)。表达式boost::bind(f, arg1, arg2, ...)表示“返回一个调用f(arg1, arg2, ...)”的无效仿函数。

也就是说,您可以使用以下表达式来创建线程:

GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain))

答案 4 :(得分:1)

如果您的对象是仿函数,即具有operator(),则可以将其实例传递给boost::threadoperator()不需要是静态的。例如:

#include <boost/thread.hpp>

struct th {
    void operator()();
};

void th::operator()()
{
    for (;;) {
        // stuff
    }
}

int main()
{
    th t;
    boost::thread my_thread( t ); // takes a copy of t !
    my_thread.join(); // blocks
    return 0;
}