在继承的类中启动线程

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 读取它,你会遇到数据竞争。 是的,但在这种情况下它不会干扰。并非总是存在需要原子变量的数据竞争。阅读有关障碍如何工作的信息,您就会明白。在这种情况下,非原子将起作用。而且,事实上,我只是修复了他的代码,尽可能地接近原始代码。这个变量甚至没有被使用。

以上是关于在继承的类中启动线程的主要内容,如果未能解决你的问题,请参考以下文章

java中如何启动一个新的线程

java线程 — 创建和启动线程

线程的启动(转)

Java创建多线程方式之一:继承Thread类

Android-创建启动线程的两种方式

3种启动线程的方式