我的线程功能不会停止我想要的线程

时间:2019-11-17 16:15:07

标签: c++ multithreading

我正在尝试制作一个秒表类,该类具有一个单独的递减计数的线程。 这里的问题是,当我使用取消功能或尝试在超时后再次设置秒表时,程序崩溃。目前,我确定这是由于某些线程问题所致,可能是由于滥用所致。有没有人可以告诉我为什么它不起作用并可以帮助我使其起作用?

 Stopwatch.h

 class Stopwatch
    {
    public:
        void Run(uint64_t ticks);
        void Set(uint64_t ms);
        void Cancel();

    private:
        std::thread mythread;
    };



Stopwatch.cpp

void Stopwatch::Run(uint64_t ticks)
{
  uint64_t clockCycles = ticks;

  while(clockCycles > 0){
    std::this_thread::sleep_for(std::chrono::milliseconds(1));
    clockCycles--;
  }

  //do anything timeout related, probab a cout in the future
}

void Stopwatch::Set(uint64_t ms)
{
    mythread = std::thread(&Timer::Run, this, ms);
}

void Stopwatch::Cancel()
{
    mythread.join();
}

我想要的是调用秒表来设置时间并获得一些超时反应。使用取消功能可以随时停止。之后,使用set函数可以重新启动它。

1 个答案:

答案 0 :(得分:1)

如注释中所述,您必须始终始终为可连接的join调用detachstd::thread(即具有或具有关联的运行线程)。该代码无法在三个地方做到这一点。在Set中,人们使用std::thread的移动分配来分配给线程,而无需考虑其先前的内容。因此,多次调用Set而不调用Cancel可以保证终止。在Stopwatch的移动分配运算符或析构函数中也没有这样的调用。

第二,因为Cancel仅调用join,所以它将在返回之前等待超时发生并执行,而不是取消计时器。要取消计时器,必须通知线程。另一方面,线程中的Run循环必须有一种通知的方法。传统的方法是使用condition_variable。

例如:

class Stopwatch
{
public:
    Stopwatch() = default;

    Stopwatch(const Stopwatch&) = delete;
    Stopwatch(Stopwatch&&) = delete;
    Stopwatch& operator=(const Stopwatch&) = delete;
    Stopwatch& operator=(Stopwatch&& other) = delete;

    ~Stopwatch()
    {
        Cancel();
    }

    void Run(uint64_t ticks)
    {
        std::unique_lock<std::mutex> lk{mutex_};
        cv_.wait_for(lk, std::chrono::milliseconds(ticks), [&] { return canceled_; });
        if (!canceled_)
            /* timeout code here */;
    }

    void Set(uint64_t ms)
    {
        Cancel();
        thread_ = std::thread(&Stopwatch::Run, this, ms);
    }

    void Cancel()
    {
        if (thread_.joinable())
        {
            {
                std::lock_guard<std::mutex> lk{mutex_};
                canceled_ = true;
            }
            cv_.notify_one();
            thread_.join();
        }
    }

private:
    bool canceled_ = false;
    std::condition_variable cv_;
    std::mutex mutex_;
    std::thread thread_;
};