gpt4 book ai didi

c++ - boost::asio::deadline_timer::async_wait 不触发回调

转载 作者:搜寻专家 更新时间:2023-10-31 01:44:30 26 4
gpt4 key购买 nike

我得到了 boost io_service在一个线程中运行,我想在客户端发生某个事件后 6 秒在该线程中触发回调,如果该客户端已经在运行,则重置该客户端的计时器。

我维护一个 unordered_map<string, shared_ptr<deadline_timer>>每个客户都有一个计时器。

但是,在设置 async_wait 时,我的回调在分配的时间后不会触发(io_service 正在运行),当我重置指针时它也不会触发(带有错误代码)(它应该调用现有计时器的析构函数,导致它发布到服务)。我该如何解决这个问题?

这是我代码的相关部分:

auto it = timersByClientId.find(clientId);
if (it == timersByClientId.end())
{
onLogonChangeCallback(clientId, true);
timersByClientId[clientId].reset(
new boost::asio::deadline_timer(replyService, boost::posix_time::seconds(6))
);
it = timersByClientId.find(clientId);
}
else
{
// Cancel current wait operation (should fire the callback with an error code)
it->second.reset(
new boost::asio::deadline_timer(replyService, boost::posix_time::seconds(6))
);
}
it->second->async_wait([this, clientId](const boost::system::error_code& err) {
if (!err)
{
onLogonChangeCallback(clientId, false);
}
});

如果它改变了什么,我在 Visual C++ 2010 下运行并 boost 1.47.0。

最佳答案

您的代码/看起来/还不错。

我不确定您是如何得出这样的结论,即您的完成处理程序不会“[...] 在我重置指针时触发(带有错误代码)”。您忽略了这种情况(lambda 中没有 else 分支)。

逻辑写的更清楚如何?

void foo(int clientId) {
shared_timer& timer = timersByClientId[clientId];

if (!timer)
onLogonChangeCallback(clientId, true);

timer = make_timer(); // reset

timer->async_wait([this, clientId](const boost::system::error_code& err) {
if (!err)
onLogonChangeCallback(clientId, false);
});
}

这是一个完整的演示,其中包含 else 分支,让您了解发生了什么。我假设有 1 个服务线程。

查看 Live On Coliru .

测试负载是在约 0.5 秒内在 16 个帐户上进行 100 个 session 事件。总运行时间约为 1.5 秒,因为我已将 Coliru 的 session 到期时间从 6 秒减少到 1 秒。

如果不想LogonManager的析构函数等待所有session过期,那么在加入后台线程之前清空session表:

~LogonMonitor() {
work = boost::none;
timersByClientId.clear();
background.join();
}

完整 list

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/optional.hpp>
#include <boost/make_shared.hpp>

struct LogonMonitor {
LogonMonitor()
: work(io_service::work(replyService)), background([this]{ replyService.run(); })
{ }

~LogonMonitor() {
work = boost::none;
// timersByClientId.clear();
background.join();
}

void foo(int clientId) {
shared_timer& timer = timersByClientId[clientId];

if (!timer)
onLogonChangeCallback(clientId, true);

timer = make_timer(); // reset

timer->async_wait([this, clientId](const boost::system::error_code& err) {
if (!err)
onLogonChangeCallback(clientId, false);
else
std::cout << "(cancel " << clientId << " timer)" << std::endl;
});
}

private:
using io_service = boost::asio::io_service;
using timer = boost::asio::deadline_timer;
using shared_timer = boost::shared_ptr<timer>;

io_service replyService;
boost::optional<io_service::work> work;
boost::thread background;

std::map<int, shared_timer> timersByClientId;

shared_timer make_timer() {
return boost::make_shared<timer>(replyService, boost::posix_time::seconds(/*6*/1));
}

void onLogonChangeCallback(int clientId, bool newLogon)
{
std::cout << __FUNCTION__ << "(" << clientId << ", " << newLogon << ")" << std::endl;
}
};

int main()
{
LogonMonitor instance;
for (int i = 0; i < 100; ++i)
{
instance.foo(rand() % 16);
boost::this_thread::sleep_for(boost::chrono::milliseconds(rand() % 10));
}
}

关于c++ - boost::asio::deadline_timer::async_wait 不触发回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23434876/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com