C++ 如何杀死或"refresh"线程?

C++ How to kill or "refresh" a thread?

本文关键字:refresh 线程 何杀死 C++      更新时间:2023-10-16

假设我们有两个函数,"waitForShortstTime"answers"addTime"。

void waitForShortestTime(tm time)
{
sleep_until(system_clock::from_time_t (timelocal(&time)));
cout << "done" << endl;
}

所以这个线程正在等待一段时间。这是一系列时间中可用的最短时间。但在另一个线程中,用户调用"addTime",这会为该系列添加另一个时间。添加的时间可能会比"线程B"等待的时间更短,所以我想杀死那个线程并"刷新它",这样它在等待之前会再次检查最短的时间。

Schedule mySchedule;
thread t(&Schedule::lookForShortTime, mySchedule); //thread is set up.
//user input
mySchedule.addTime(time); //new time is added by user.
//kill thread
thread t(&Schedule::lookForShortTime, mySchedule); //new thread to consider new time.

但我想知道如何先杀死当前线程。

您是否考虑过使用条件变量?看见https://en.cppreference.com/w/cpp/thread/condition_variable.

与其杀死线程,不如向它发送一个信号,让它苏醒,然后采取适当的行动。

我强烈建议您购买并阅读《C++并发操作》一书(https://www.manning.com/books/c-plus-plus-concurrency-in-action-second-edition)因为它给出了很多关于使用标准C++编写多线程代码的解释。

因此,每次需要在任何现有事件之前添加要处理的事件时,都可以向该线程发出停止信号,等待它停止,然后启动另一个线程。

或者,你也可以简单地启动另一个线程,为新事件设置一个较短的计时器,再加上最长的等待时间,这是一个很好的折衷方案,既可以在之前添加事件,也可以在唤醒次数太多的情况下实现。

例如,假设大多数工作是在接下来的30分钟或更长时间内完成的,而您很少在接下来的5分钟内有新工作。然后,您可以告诉线程等待5分钟,当它醒来时,它会检查是否应该在接下来的5分钟结束前安排任何作业,如果是,请使用较小的等待时间。

或者,如果所需的精度不高(比如说你需要在计划时间的一分钟或两分钟内检查),你可以一直等待,最多等待一到两分钟,然后检查你现在是否有事情要做。

在实践中,也没有必要杀死线程。您唤醒它,让线程检查是否有事情要做,如果没有,下一次应该处理项目的时间是什么,并将其用于等待时间。

该事件也可用于退出应用程序。

有时,使用最大延迟可以帮助确保如果某个事件以某种方式丢失,数据将在一定的时间内得到处理,从而使应用程序更有充分的证据。此外,您可以进行一些健康检查,例如,在很长的延迟之后,您仍然没有处理上一个作业(例如,您有一个导致无限循环的错误)。

这将完成您需要做的事情。它目前需要fmt库,但很容易更改。它使用一个条件变量来实现魔术:

#include <fmt/core.h>
#include <iostream>
#include <thread>
#include <queue>
#include <vector>
#include <condition_variable>
#include <chrono>
#include <utility>
#include <string>
#include <mutex>
using timed_msg_t = ::std::pair<::std::chrono::system_clock::time_point,
::std::string>;
class time_smaller
{
public:
bool operator ()(timed_msg_t const &a, timed_msg_t const &b)
{
return b.first < a.first;
}
};
using timer_queue = ::std::priority_queue<timed_msg_t,
::std::vector<timed_msg_t>,
time_smaller>;
using ::std::mutex;
using ::std::condition_variable;
using ::std::thread;
using ::std::unique_lock;
static auto const start = ::std::chrono::system_clock::now();
void timer_queue_thread(mutex &queue_mutex,
condition_variable &queue_condition,
timer_queue &q)
{
unique_lock<mutex> qlock(queue_mutex);
while (!q.empty()) {
auto now = ::std::chrono::system_clock::now();
auto const &top = q.top();
if (top.first <= now) {
double milliseconds_from_start = (now - start) / ::std::chrono::milliseconds(1);
::fmt::print("At time: {}ms - "{}"n", milliseconds_from_start, top.second);
q.pop();
} else {
queue_condition.wait_until(qlock, top.first);
}
}
}
int main()
{
timer_queue tq;
mutex queue_mutex;
condition_variable queue_condition;
{
unique_lock<mutex> qlock(queue_mutex);
tq.emplace(start + 60 * ::std::chrono::seconds(1), "Starting event.");
}
::std::thread timer_processing{timer_queue_thread, ::std::ref(queue_mutex), ::std::ref(queue_condition), ::std::ref(tq)};
while (true) {
int seconds;
::std::string msg;
::std::cout << "Enter a time and message:n";
::std::cin >> seconds;
getline(::std::cin, msg);
{
unique_lock<mutex> qlock(queue_mutex);
auto const qtime = ::std::chrono::system_clock::now() + seconds * ::std::chrono::seconds(1);
tq.emplace(qtime, msg);
queue_condition.notify_one();
}
}
return 0;
}