std::thread 计时器

Timer with std::thread

我正在使用计时器 class 在不同的线程上执行操作,下面的示例代码是从另一个 SO 问题 HERE

复制的
#include <thread>
#include <chrono>
#include <functional>

class Timer
{
public:
    ~Timer();
    Timer() noexcept;

    typedef std::chrono::milliseconds Interval;
    typedef std::function<void(void)> Timeout;

public:
    void start(const Interval& interval, const Timeout& timeout);
    void stop();

private:
    std::thread mThread;    /** Timer thread */
    bool mRunning = false;  /** Timer status */
};

实现时附上会出现问题的注释:

Timer::~Timer()
{
}

Timer::Timer() noexcept
{
}

void Timer::start(const Interval& interval, const Timeout& timeout)
{
    mRunning = true;

    mThread = std::thread([&]()
        {
            while (mRunning == true)
            {
                std::this_thread::sleep_for(interval);

                // std::abort will be called here
                timeout();
            }
        });
}

void Timer::stop()
{
    mRunning = false;
    mThread.join();
}

测试计时器的示例:

#include <iostream>

int main()
{
    Timer tm;

    tm.start(std::chrono::milliseconds(1000), []
        {
            std::cout << "Hello!" << std::endl;
        });

    std::this_thread::sleep_for(std::chrono::seconds(4));
    tm.stop();
}

我无法理解为什么在 lambda 中执行 std::function 时调用 std::abort,我该如何解决这个问题?

您的 start 函数的参数通过引用传递。在您的 lambda 中,您通过引用捕获它们。当您开始调用该 lambda 时,您捕获的所有内容都已被销毁,因此您导致了未定义的行为。

此外,请确保使用 atomic<bool> 而不是常规的 bool:

#include <thread>
#include <chrono>
#include <functional>
#include <cstdio>
#include <atomic>

class Timer {
public:
    ~Timer() {
        if (mRunning) {
            stop();
        }
    }
    typedef std::chrono::milliseconds Interval;
    typedef std::function<void(void)> Timeout;

    void start(const Interval &interval, const Timeout &timeout) {
        mRunning = true;

        mThread = std::thread([=]() {
            while (mRunning) {
                std::this_thread::sleep_for(interval);

                timeout();
            }
        });
    }
    void stop() {
        mRunning = false;
        mThread.join();
    }

private:
    std::thread mThread{};
    std::atomic_bool mRunning{};
};

int main() {
    Timer tm;

    tm.start(std::chrono::milliseconds(1000), [] {
        std::puts("Hello!");
    });

    std::this_thread::sleep_for(std::chrono::seconds(4));
}

P.S。你可能想根据这个想法的发展方向来研究协程。