C++ 在类向量中线程化成员函数

C++ 在类向量中线程化成员函数,c++,boost,multithreading,C++,Boost,Multithreading,类MyClass { 公众: void DoSomething(){}; }; std::向量A; int main(int argc,char*const argv[] { 我的a级; A.推回(A); boost::threadnewthread(&MyClass::DoSomething,&A.back()); } 它可以编译,但预期不会起作用。有什么帮助吗?(由于缺少其他输入,我假设您正在处理某些VS版本、某些Windows版本) (1) 我假设你试图将&A.作为一个隐含的“this”

类MyClass { 公众: void DoSomething(){}; };

std::向量A;
int main(int argc,char*const argv[]
{
我的a级;
A.推回(A);
boost::threadnewthread(&MyClass::DoSomething,&A.back());
}
它可以编译,但预期不会起作用。有什么帮助吗?

(由于缺少其他输入,我假设您正在处理某些VS版本、某些Windows版本)

(1) 我假设你试图将&A.作为一个隐含的“this”参数传递回去。这对常规成员函数不起作用,它们被定义为-这意味着函数需要ecx寄存器中的'This'参数,而不是堆栈上的参数。尝试将DoSomething声明为stdcall或static(使用显式“this”参数)

(2) 删除函数的地址。Boost::thread构造函数要求第一个参数按原样“可调用”:

可能最终会起作用。

(由于缺少其他输入,我假设您正在使用某些VS版本,某些Windows版本)

(1) 我假设你试图将&A.作为一个隐含的“this”参数传递回去。这对常规成员函数不起作用,它们被定义为-这意味着函数需要ecx寄存器中的'This'参数,而不是堆栈上的参数。尝试将DoSomething声明为stdcall或static(使用显式“this”参数)

(2) 删除函数的地址。Boost::thread构造函数要求第一个参数按原样“可调用”:


可能最终会工作。

第一个问题是您的主函数正在生成一个线程,然后立即退出。在进程终止之前,线程几乎没有机会运行。因此,您至少需要等待线程完成,您可以通过将
newThread.join()
添加到
main
的末尾来完成,因此:

int main(int argc, char* const argv[])
{
    MyClass a;
    A.push_back(a);
    boost::thread newThread(&MyClass::DoSomething, &A.back());
    newThread.join();
    return 0;
}
另一个问题是线程对象作为局部变量与
main
在同一范围内。虽然您可以在简单的情况下执行此操作,但您需要注意
boost::thread
对象的范围,该对象的生命周期至少与您期望的线程运行时间相同

在对象需要在成员函数上运行线程的情况下,最好将线程对象封装在对象中,并使用一个简单的
run()
方法启动工作线程。这样,您就可以在一个地方封装所有状态和线程管理,以及您可能需要的任何互斥体和条件变量。一个简单的例子如下:

class Worker
{
public:

    Worker();

    void start(int N)
    {
        m_Thread = boost::thread(&Worker::processQueue, this, N);
    }

    void join()
    {
        m_Thread.join();
    }

    // Worker thread where all processing occurs
    void processQueue(int N);

private:

    boost::thread m_Thread;
};
您可能还想添加一些东西,比如返回线程状态的标志(例如,running、completed、waiting等)

我注意到您的示例使用了对象实例的向量(即按值存储)。请注意,不要无意中执行导致隐式创建副本的操作,因为这可能会导致线程出现各种问题。(这就是为什么
boost::thread
对象是不可复制的。)


我在上写了一篇文章,解释了创建线程的各种方法,包括如何在成员函数上运行线程(请参见类型5)。

第一个问题是主函数正在生成线程,然后立即退出。在进程终止之前,线程几乎没有机会运行。因此,您至少需要等待线程完成,您可以通过将
newThread.join()
添加到
main
的末尾来完成,因此:

int main(int argc, char* const argv[])
{
    MyClass a;
    A.push_back(a);
    boost::thread newThread(&MyClass::DoSomething, &A.back());
    newThread.join();
    return 0;
}
另一个问题是线程对象作为局部变量与
main
在同一范围内。虽然您可以在简单的情况下执行此操作,但您需要注意
boost::thread
对象的范围,该对象的生命周期至少与您期望的线程运行时间相同

在对象需要在成员函数上运行线程的情况下,最好将线程对象封装在对象中,并使用一个简单的
run()
方法启动工作线程。这样,您就可以在一个地方封装所有状态和线程管理,以及您可能需要的任何互斥体和条件变量。一个简单的例子如下:

class Worker
{
public:

    Worker();

    void start(int N)
    {
        m_Thread = boost::thread(&Worker::processQueue, this, N);
    }

    void join()
    {
        m_Thread.join();
    }

    // Worker thread where all processing occurs
    void processQueue(int N);

private:

    boost::thread m_Thread;
};
您可能还想添加一些东西,比如返回线程状态的标志(例如,running、completed、waiting等)

我注意到您的示例使用了对象实例的向量(即按值存储)。请注意,不要无意中执行导致隐式创建副本的操作,因为这可能会导致线程出现各种问题。(这就是为什么
boost::thread
对象是不可复制的。)


我在上写了一篇文章,解释了创建线程的各种方法,包括如何在成员函数上运行线程(请参见类型5)。

哎呀,对不起。现在应该编译了。哎呀,对不起。现在应该编译了。你的文章很棒。我希望在实际的boost文档中有这样的东西,我花了很多时间来关注它,在我弄清楚之前,但是你的文档中有一切:-)谢谢!我试着写下我学到的东西。我还有两篇文章是草稿,我希望很快就可以发表。你们的文章很棒。我希望在实际的boost文档中有这样的东西,我花了很多时间来关注它,在我弄清楚之前,但是你的文档中有一切:-)谢谢!我试着写下我学到的东西。我还有两篇文章是草稿,我希望很快能写出来。