我正在尝试安全地取消一个boost::asio::basic_waitable_timer<std::chrono::steady_clock>
。
根据这个答案,这段代码应该可以完成此工作:
timer.get_io_service().post([&]{timer.cancel();})
很抱歉,它对我不起作用。
我做错了什么吗?
这是我的代码:
#include <iostream>
#include "boost/asio.hpp"
#include <chrono>
#include <thread>
#include <random>
boost::asio::io_service io_service;
boost::asio::basic_waitable_timer<std::chrono::steady_clock> timer(io_service);
std::atomic<bool> started;
void handle_timeout(const boost::system::error_code& ec)
{
if (!ec) {
started = true;
std::cerr << "tid: " << std::this_thread::get_id() << ", handle_timeout\n";
timer.expires_from_now(std::chrono::milliseconds(10));
timer.async_wait(&handle_timeout);
} else if (ec == boost::asio::error::operation_aborted) {
std::cerr << "tid: " << std::this_thread::get_id() << ", handle_timeout aborted\n";
} else {
std::cerr << "tid: " << std::this_thread::get_id() << ", handle_timeout another error\n";
}
}
int main() {
std::cout << "tid: " << std::this_thread::get_id() << ", Hello, World!" << std::endl;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(1, 100);
for (auto i = 0; i < 1000; i++) {
started = false;
std::thread t([&](){
timer.expires_from_now(std::chrono::milliseconds(0));
timer.async_wait(&handle_timeout);
io_service.run();
});
while (!started) {};
auto sleep = dis(gen);
std::cout << "tid: " << std::this_thread::get_id() << ", i: " << i << ", sleeps for " << sleep << " [ms]" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
timer.get_io_service().post([](){
std::cerr << "tid: " << std::this_thread::get_id() << ", cancelling in post\n";
timer.cancel();
});
// timer.cancel();
std::cout << "tid: " << std::this_thread::get_id() << ", i: " << i << ", waiting for thread to join()" << std::endl;
t.join();
io_service.reset();
}
return 0;
}
这是输出结果:
如您所见,...
tid: 140737335076608, 处理超时
tid: 140737335076608, 处理超时
tid: 140737353967488, i: 2, 等待线程加入()
tid: 140737335076608, 在post中取消
tid: 140737335076608, 处理超时中止
tid: 140737353967488, i: 3, 睡眠21 [ms]
tid: 140737335076608, 处理超时
tid: 140737353967488, i: 3, 等待线程加入()
tid: 140737335076608, 处理超时
tid: 140737335076608, 在post中取消
tid: 140737335076608, 处理超时
tid: 140737335076608, 处理超时
tid: 140737335076608, 处理超时
tid: 140737335076608, 处理超时
tid: 140737335076608, 处理超时
...
永远继续...
timer.cancel()
被从适当的线程调用:
但之后没有tid: 140737335076608, 在post中取消
之后,主线程永远等待。tid: 140737335076608, 处理超时中止
deadline_timer
)。请参阅https://dev59.com/ZGcs5IYBdhLWcg3wgkMQ#12801042。希望这能够明确表达`cancel()`不是线程安全的事实,并且这已在文档中说明(没有人会否认这一点)。 - seheboost::asio::signal_set
?或者我应该使用一些“shutdown”标志? - hudacsignal_set.clear(...);
(现在当你收到信号0时,这意味着你应该关闭)。 - sehe