简单的线程计时器,请检查是否正常

Simple threaded timer, sanity check please

本文关键字:检查 是否 线程 计时器 简单      更新时间:2023-10-16

我制作了一个非常简单的线程计时器类,考虑到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;
};

我想一个更好的问题可能是请某人给我指一个非常简单的线程计时器,如果某个地方已经有了。

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

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

由于某种原因,结果总是超时。它似乎从未得到信号,因此从未停止。这是正确的吗?notify_all是否应该取消阻止wait_fo?

只有当线程当时正好在cv上时,它才能解除阻止。您可能要做的是在线程开始运行并开始等待之前(或者可能在callback运行时)调用Start,然后立即调用Stop。在这种情况下,线程将永远不会得到通知。

您的代码存在另一个问题。在某些实现中,即使您没有显式调用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;
...

有了这些变化,你的计时器应该可以工作,但要意识到"[std::condition_variable::wait_for]可能会因为调度或资源争用延迟而阻塞超过timeout_duration",用cppreference.com的话说。

如果某个地方已经有线程计时器的话,请给我介绍一个非常简单的线程计时器。

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