C++ 在类向量中线程化成员函数
类MyClass { 公众: void DoSomething(){}; };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”
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文档中有这样的东西,我花了很多时间来关注它,在我弄清楚之前,但是你的文档中有一切:-)谢谢!我试着写下我学到的东西。我还有两篇文章是草稿,我希望很快能写出来。