在继承的类中启动线程
Posted
技术标签:
【中文标题】在继承的类中启动线程【英文标题】:Starting threads in inherited classes 【发布时间】:2015-10-16 14:55:49 【问题描述】:我希望在项目的类中运行线程。也就是说,当我创建一个对象,然后调用一个成员函数“StartThread”,它就会开始执行我在对象中的MainThreadFunction。我可以在所有不同的类中重新编写关于如何启动线程的类似代码,但使用继承并拥有一个名为 ThreadClass 的基类更有意义,其他类可以从该基类继承。
MainThreadFunction 当然是虚拟的,并且根据继承它的类的类型不同地实现。问题是,我不确定我是否以正确的方式去做。当我在不同的类中实现这个虚函数并调用继承的函数StartThread时,它是否应该使用这种方法执行正确的MainThreadFunction?创建一个 GaugeController 的对象,我不确定是否应该用一些东西来初始化基础构造函数。
我对线程和继承非常陌生,任何想法或帮助将不胜感激。谢谢。
我的主要问题是这是否是一个好的设计,让类从我的 ThreadClass 继承以具有线程特性。
//In ThreadClass.h
class ThreadClass
public:
ThreadClass();
//virtual ~ThreadClass();
void StartThread();
virtual void MainThreadFunction();
protected:
std::thread t;
bool threadStop = false;
;
////////////////////////////////////////////////////////////////////////////
// In ThreadClass.cpp
ThreadClass::ThreadClass() : t()
void ThreadClass::StartThread()
t = std::thread(&ThreadClass::MainThreadFunction, this);
void ThreadClass::MainThreadFunction()
// The implementation will be different for each child class
/////////////////////////////////////////////////////////////////////////
// In GaugeController.h
class GaugeController : public ThreadClass
public:
GaugeController(DataChannel& dc);
~GaugeController();
void StartThread();
virtual void MainThreadFunction();
void WriteData(float data);
;
【问题讨论】:
对不起,您的代码可以编译吗?因为,当我使用 MS 的线程机制 (CreateThread) 时 - 您无法使用非静态类方法启动线程(因为它与对象绑定,并且不能从对象的上下文中调用) . 以上ThreadClass
中的thread
是什么?
@JohannGerell 我的猜测是:cplusplus.com/reference/thread/thread
嗨,对不起,我省略了很多代码。我正在使用 std::thread。当我在 GaugeController 类中拥有所有相同的逻辑时,一切都编译得很好,但我现在正试图将线程启动功能移出类
@Engineer999,究竟是什么不起作用?你自己试过你的代码吗?它对我来说似乎是正确的(好吧,除了不等待你的线程完成,如果你的主线程在你的工作线程之前用完了要做的事情)。
【参考方案1】:
您“有点”为std::thread
制作了一个包装器,这就是您想要使用的。所以你可能正在寻找这样的东西:
//In ThreadClass.h
class ThreadClass
public:
ThreadClass();
virtual ~ThreadClass()
void StartThread();
virtual void MainThreadFunction() = 0; // this good for you
protected:
std::thread t;
bool threadStop = false;
;
////////////////////////////////////////////////////////////////////////////
// In ThreadClass.cpp
ThreadClass::ThreadClass() : t()
void ThreadClass::StartThread()
t = std::thread(&ThreadClass::MainThreadFunction, this);
// you must join your thread!
void ThreadClass::join()
t.join();
/////////////////////////////////////////////////////////////////////////
// In GaugeController.h
class GaugeController : public ThreadClass
public:
GaugeController(DataChannel& dc);
virtual ~GaugeController()
void StartThread();
virtual void MainThreadFunction();
void WriteData(float data);
;
使用join()
!默认情况下,来自std::thread
的线程是可连接的,
所以你需要调用join()
以等待线程完成
它的工作。其他选择是分离你的线程......谷歌它,
这样您就可以更好地理解可连接线程之间的区别
和分离的线程。
虚拟析构函数在 99% 的情况下都是个好主意!保留它们。它们对于根据类层次结构正确清理您的实例很有用。
注意MainThreadFunction
定义中的= 0
。它是可选的,但我认为它适合您。一旦必须扩展ThreadClass
,您基本上不需要实现什么都不做的方法。你把你的ThreadClass
变成一个抽象类。
【讨论】:
Wagner,在析构函数内部,我在执行 threadStop = true 然后 t.join() 以等待线程在对象销毁之前完成。我应该在析构函数之前加入线程吗?干杯 downvote:bool threadStop = false;
不是线程安全的,至少使用原子。
它不需要是原子的。
@WagnerPatriota 如果你从主线程设置它,然后从thread t
读取它,你会遇到数据竞争。
是的,但在这种情况下它不会干扰。并非总是存在需要原子变量的数据竞争。阅读有关障碍如何工作的信息,您就会明白。在这种情况下,非原子将起作用。而且,事实上,我只是修复了他的代码,尽可能地接近原始代码。这个变量甚至没有被使用。以上是关于在继承的类中启动线程的主要内容,如果未能解决你的问题,请参考以下文章