英文:
Unable to process boost asio:- async read buffer's callback asynchronously
问题
我使用boost::asio::async_read()
方法来异步获取来自服务器的响应,该服务器需要10秒来处理请求。我成功地读取了响应。但我附加了回调函数来处理接收到的响应,这需要10秒的时间。我不知道如何异步处理该回调。
void read_response(std::string data)
{
cout << data << endl;
sleep(10);
// 如果您认为 sleep 会以不同的方式工作,如果我从这里发送另一个 REST API 请求,仍然会阻止处理该函数
}
boost::asio::async_read(socket, boost::asio::buffer(buffer), [&](const boost::system::error_code&
error,
std::size_t bytes_transferred) {
io_context.post([&]() {
read_response(buffer.data());
// read_response 不会异步处理
});
});
我尝试将函数发布到 io_context
,我尝试使用
std::async(std::launch::deferred, read_handler, error, bytes_transferred, buffer.data()).wait();
我是异步编程和C++编程的新手。
英文:
I'm using boost::asio::async_read() method to asynchronously get response from server which take 10 second to process request. I am able to read response successfully. but I am attaching callback to this function to process received response which take 10 seconds. I am unable to find how i can process that callback asynchronously.
void read_response(std::string data)
{
cout << data << endl;
sleep(10);
// if you think sleep works differently if i send another rest api request from here still this function blocks the processing
}
boost::asio::async_read(socket, boost::asio::buffer(buffer), [&](const boost::system::error_code&
error,
std::size_t bytes_transferred) {
io_context.post([&]() {
read_response(buffer.data());
//read_response is not processing asynchronously
});
});
I tried posting function to io_context, i tried using
std::async(std::launch::deferred, read_handler,error,bytes_transferred,buffer.data()).wait() ;
I am new to asyn programming and c++ programming.
答案1
得分: 1
以下是您要翻译的部分:
Indeed, don't do blocking operations on the IO service. Or grow the thread pool to accomodate for the maximum number of concurrent tasks that must be supported.
In all circumstances, copy the message into your read handler, instead of passing the buffer directly (as you did) as that invites race conditions/stale references.
Let's demonstrate using httpbin.org/delay:
#include <boost/asio.hpp>
#include <iomanip>
#include <iostream>
namespace asio = boost::asio;
using asio::ip::tcp;
using namespace std::chrono_literals;
std::string const request = "GET /delay/10 HTTP/1.1\r\nHost: httpbin.org\r\n\r\n";
void read_response(std::string data) {
std::cout << "Asynchronously received response: " << quoted(data) << std::endl;
sleep(10);
}
int main() {
asio::io_context ioc(1);
asio::thread_pool work(10); // support 10 tasks along-side async IO
tcp::socket conn(ioc);
connect(conn, tcp::resolver(ioc).resolve("httpbin.org", "80"));
write(conn, asio::buffer(request));
std::string buf;
async_read_until( //
conn, asio::dynamic_buffer(buf), "\r\n\r\n",
[&work, &buf](boost::system::error_code ec, size_t n) {
std::cout << "\n*** Completion " << ec.message() << ", " << n << std::endl;
post(work, [msg = buf.substr(0, n)] {
// NOTE: lambda owns msg, not a reference to `buf`
read_response(std::move(msg));
});
});
std::thread([&ioc] {
ioc.run();
std::cout << "\n*** IO complete" << std::endl;
}).detach();
for (int i = 0; i < 15; ++i) {
std::cout << "." << std::flush;
std::this_thread::sleep_for(1s);
}
work.join();
std::cout << "\n*** Work Done" << std::endl;
}
This shows work continuing, "asynchronously" (relative to IO) well after ioc
completes.
英文:
Indeed, don't do blocking operations on the IO service. Or grow the thread pool to accomodate for the maximum number of concurrent tasks that must be supported.
In all circumstances, copy the message into your read handler, instead of passing the buffer directly (as you did) as that invites race conditions/stale references.
Let's demonstrate using httpbin.org/delay:
#include <boost/asio.hpp>
#include <iomanip>
#include <iostream>
namespace asio = boost::asio;
using asio::ip::tcp;
using namespace std::chrono_literals;
std::string const request = "GET /delay/10 HTTP/1.1\r\nHost: httpbin.org\r\n\r\n";
void read_response(std::string data) {
std::cout << "Asynchronously received response: " << quoted(data) << std::endl;
sleep(10);
}
int main() {
asio::io_context ioc(1);
asio::thread_pool work(10); // support 10 tasks along-side async IO
tcp::socket conn(ioc);
connect(conn, tcp::resolver(ioc).resolve("httpbin.org", "80"));
write(conn, asio::buffer(request));
std::string buf;
async_read_until( //
conn, asio::dynamic_buffer(buf), "\r\n\r\n",
[&work, &buf](boost::system::error_code ec, size_t n) {
std::cout << "\n*** Completion " << ec.message() << ", " << n << std::endl;
post(work, [msg = buf.substr(0, n)] {
// NOTE: lambda owns msg, not a reference to `buf`
read_response(std::move(msg));
});
});
std::thread([&ioc] {
ioc.run();
std::cout << "\n*** IO complete" << std::endl;
}).detach();
for (int i = 0; i < 15; ++i) {
std::cout << "." << std::flush;
std::this_thread::sleep_for(1s);
}
work.join();
std::cout << "\n*** Work Done" << std::endl;
}
This shows work continuing, "asynchronously" (relative to IO) well after ioc
completes:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论