简单的线程计时器,请检查健全

时间:2015-03-05 17:01:00

标签: c++ multithreading timer

我已经制作了一个非常简单的线程计时器类,并且考虑到MT代码的缺陷,我想要进行理智检查。这里的想法是启动一个线程然后连续循环等待一个变量。如果等待超时,则超过间隔,我们调用回调。如果变量已发出信号,则线程应该退出,我们不会调用回调。

我不确定的事情之一就是我的代码在析构函数中发生了什么,因为线程可以在那里连接(只是)。我可以在析构函数中加入一个线程以确保它已完成吗?

这是班级:

class TimerThreaded
{
public:

    TimerThreaded() {}
    ~TimerThreaded()
    {           
        if (MyThread.joinable())
            Stop();             
    }

    void Start(std::chrono::milliseconds const & interval, std::function<void(void)> const & callback)
    {   
        if (MyThread.joinable())
            Stop();

        MyThread = std::thread([=]()
        {
            for (;;)
            {
                auto locked = std::unique_lock<std::mutex>(MyMutex);
                auto result = MyTerminate.wait_for(locked, interval);

                if (result == std::cv_status::timeout)
                    callback();
                else
                    return;
            }
        });
    }

    void Stop()
    {
        MyTerminate.notify_all();
    }

private:

    std::thread MyThread;
    std::mutex MyMutex;
    std::condition_variable MyTerminate;
};

我想更好的问题可能是要求某人指出一个非常简单的线程计时器,如果有一个已经可用的话。

1 个答案:

答案 0 :(得分:2)

  

我可以加入析构函数中的线程以确保它已完成吗?

不仅可以,而且这种做法非常典型。如果线程实例在被销毁时是可连接的(即仍在运行),则会调用terminate

  

由于某种原因,结果总是超时。它似乎永远不会发出信号,因此永远不会停止。这是对的吗? notify_all应该取消阻止wait_for?

如果线程恰好在cv上,它只能解锁。您可能正在做的是在线程开始运行并开始等待(或可能在Start运行时)之前调用Stop然后立即callback。在这种情况下,线程永远不会被通知。

您的代码还有另一个问题。即使您没有明确调用notify_X,也可能会在某些实现中虚假地唤醒被阻止的线程。这会导致你的计时器无缘无故地停止。

我建议您添加一个标志变量,指示是否已调用Stop。这将解决上述两个问题。这是使用条件变量的典型方法。我甚至为你编写了代码:

class TimerThreaded
{
...
        MyThread = std::thread([=]()
        {
            for (;;)
            {
                auto locked = std::unique_lock<std::mutex>(MyMutex);
                auto result = MyTerminate.wait_for(locked, interval);

                if (stop_please)
                    return;
                if (result == std::cv_status::timeout)
                    callback();
            }
        });
....
    void Stop()
    {
        {
            std::lock_guard<std::mutex> lock(MyMutex);
            stop_please = true;
        }
        MyTerminate.notify_all();
        MyThread.join();
    }

...
private:
    bool stop_please = false;
...

通过这些更改,您的计时器应该可以正常工作,但确实意识到&#34; [std::condition_variable::wait_for]由于调度或资源争用延迟而导致阻塞的时间超过timeout_duration&#34;,用{{3 }}

  

指向一个非常简单的线程计时器,如果有一个已在某处可用。

我不知道标准的c ++解决方案,但现代操作系统通常提供这种功能,或者至少可以用来构建它。有关示例,请参阅linux上的cppreference.com