C ++ 11 std :: threads并等待线程完成 [英] C++11 std::threads and waiting for threads to finish

查看:467
本文介绍了C ++ 11 std :: threads并等待线程完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Timer对象的向量。每个Timer对象启动一个std ::线程,模拟一个生长期。我使用一个命令模式。

I have a vector of Timer Objects. Each Timer Object launches an std::thread that simulates a growing period. I am using a Command pattern.

发生的是每个计时器一个接一个执行,但我真正想要的是一个执行....然后一旦完成,下一个...一次完成下一个...而不干扰程序的主要执行

What is happening is each Timer is getting executed one after another but what I really want is for one to be executed....then once finished, the next one...once finished the next...while not interfering with the main execution of the program

class Timer 
{
    public:

        bool _bTimerStarted;
        bool _bTimerCompleted;

        int _timerDuration;

        virtual ~Timer() { }
        virtual void execute()=0;
        virtual void runTimer()=0;

        inline void setDuration(int _s) { _timerDuration = _s; };
        inline int getDuration() { return _timerDuration; };

        inline bool isTimerComplete() { return _bTimerCompleted; };
};

class GrowingTimer : public Timer
{
    public:
        void execute()
        {
            //std::cout << "Timer execute..." << std::endl;

            _bTimerStarted = false;
            _bTimerCompleted = false;

            //std::thread t1(&GrowingTimer::runTimer, this); //Launch a thread
            //t1.detach();

            runTimer();
        }

        void runTimer()
        {
            //std::cout << "Timer runTimer..." << std::endl;

            _bTimerStarted = true;

            auto start = std::chrono::high_resolution_clock::now();
            std::this_thread::sleep_until(start + std::chrono::seconds(20));

            _bTimerCompleted = true;

            std::cout << "Growing Timer Finished..." << std::endl; 
        }
};

class Timers
{
    std::vector<Timer*> _timers;

    struct ExecuteTimer
    {
        void operator()(Timer* _timer) { _timer->execute(); }
    };

    public:
        void add_timer(Timer& _timer) { _timers.push_back(&_timer); }

        void execute()
        {
            //std::for_each(_timers.begin(), _timers.end(), ExecuteTimer());

            for (int i=0; i < _timers.size(); i++)
            {
                 Timer* _t = _timers.at(i);
                _t->execute();

                //while ( ! _t->isTimerComplete())
                //{

                //}
            }
        }
};

执行上述操作:

Timers _timer;
GrowingTimer _g, g1;

_g.setDuration(BROCCOLI::growTimeSeconds);
_g1.setDuration(BROCCOLI::growTimeSeconds);

_timer.add_timer(_g);
_timer.add_timer(_g1);

start_timers();

}

void start_timers() 
{
    _timer.execute();
}

在Timers :: execute中我尝试了几种不同的方式来执行第一个

In Timers::execute I am trying a few different ways to execute the first and not execute the next until I somehow signal it is done.

更新:

我不会执行
我现在这样做以执行一切:

I am now doing this to execute everything:

Timers _timer;
GrowingTimer _g, g1;

_g.setDuration(BROCCOLI::growTimeSeconds);
_g1.setDuration(BROCCOLI::growTimeSeconds);

_timer.add_timer(_g);
_timer.add_timer(_g1);

//start_timers();

std::thread t1(&Broccoli::start_timers, this); //Launch a thread
t1.detach();

}

void start_timers() 
{
    _timer.execute();
}

第一次完成(我看到完成cout)使用EXEC_BAD_ACCESS在 _t-> execute(); 里面的 for循环我添加了一个cout来检查向量的大小,它是2所以两个计时器都在里面。我在控制台看到这个:

The first time completes (I see the "completed" cout), but crashes at _t->execute(); inside the for loop with an EXEC_BAD_ACCESS. I added a cout to check the size of the vector and it is 2 so both timers are inside. I do see this in the console:

this    Timers *    0xbfffd998
_timers std::__1::vector<Timer *, std::__1::allocator<Timer *> >



join()一切都完成而不会崩溃,但它阻止我的应用程序的执行,直到那些计时器完成。

if I change the detach() to join() everything completes without the crash, but it blocks execution of my app until those timers finish.

推荐答案

为什么你在这里使用线程? Timers :: execute()调用在定时器上执行,然后等待它完成, $ c>在下一个执行,依此类推。为什么不直接在 Timers :: execute()中调用计时器函数,而不是生成一个线程,然后等待它?

Why are you using threads here? Timers::execute() calls execute on a timer, then waits for it to finish, then calls execute on the next, and so forth. Why don't you just call the timer function directly in Timers::execute() rather than spawning a thread and then waiting for it?

线程允许你编写同时执行的代码。

Threads allow you to write code that executes concurrently. What you want is serial execution, so threads are the wrong tool.

更新:在更新的代码中,您运行 start_timers 在后台线程,这是好的。但是,通过分离该线程,您将使线程运行超过作用域的末尾。这意味着计时器对象 _g _g1 甚至 Timers object _timers 在线程完成之前可能被销毁。考虑到定时器线程的耗时性质,以及您使用 detach 而不是 join 以便避免你的代码阻塞,这肯定是你的问题的原因。

Update: In the updated code you run start_timers on a background thread, which is good. However, by detaching that thread you leave the thread running past the end of the scope. This means that the timer objects _g and _g1 and even the Timers object _timers are potentially destroyed before the thread has completed. Given the time-consuming nature of the timers thread, and the fact that you used detach rather than join in order to avoid your code blocking, this is certainly the cause of your problem.

如果你在一个线程上运行代码,那么你需要确保该线程访问的所有对象有一个足够长的生存期,当线程访问它们时,它们仍然有效。对于分离的线程,这是特别难以实现的,因此不建议使用分离的线程。

If you run code on a thread then you need to ensure that all objects accessed by that thread have a long-enough lifetime that they are still valid when the thread accesses them. For detached threads this is especially hard to achieve, so detached threads are not recommended.

一个选项是创建一个包含 _timers _g _g1 沿着线 t1 ,并使其析构函数与线程联接。所有你需要做的是确保对象生存,直到等待计时器完成的安全的点。

One option is to create an object containing _timers, _g and _g1 along side the thread t1, and have its destructor join with the thread. All you need to do then is to ensure that the object lives until the point that it is safe to wait for the timers to complete.

这篇关于C ++ 11 std :: threads并等待线程完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆