Reputation: 2312
I want to use boost::asio (or asio stand alone) to query multiple network devices once a minute for data via asynchronous sockets. For a test I have already implemented a Client class and a console program that does that for one device (without repetition). Something like this:
class MyClient
{
public:
MyClient(asio::io_service& io_service);
void GetData(CompletionHandler completionHandler);
};
The MyClient::GetData class uses several asynchronous operations internally where the completion of each operation triggers the next until the data are available:
The console program that uses this class works like this:
int main(...)
{
asio::io_service io_service_;
MyClient c(io_service_, ...);
...
c.GetData([](std::error_code ec, const FloatVector& values){
//do something with values
});
io_service_.run();
...
}
Now I want to use the MyClient class in a GUI program for connecting to >10 devices once a minute but I'm stuck on the overall design.
First I created a thread pool where each thread executes io_service::run() of a single io_service instance.
Now whenever my program wants to read data from the devices it would have a loop over all devices and would have to create an instance of MyClient for each and call the GetData() method.
How does that work together with the io_service now that io_service::run() is executed in the threads of a pool? Can I simply call MyClient::GetData() in the GUI thread because it uses asynchronous operations internally or do I have to call something like io_service::post() ?
Update: My code and console demo follows roughly this example: www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/example/http/client/async_client.cpp
But in a GUI program I don't want to run io_service.run() in the GUI thread. Now assume I have at least one extra thread that executes io_service.run() and a user presses a button that should start the device reading. The final completion handler should store the data in a database and update a graphical display to the user.
Maybe the button handler can simply instantiate MyClient and call GetData() on it and everything works as it should since MyClient knows the io_service and uses it f.e. in async_connect etc.
Does it work like this or am I mistaken here?
Note: at this point my question is not how to handle the data in the completion handler! It is how to correctly get the data in a multithreaded GUI program.
Upvotes: 3
Views: 1199
Reputation: 8401
Here's a rough outline of what you need to do:
Upvotes: 1
Reputation: 5387
Check this example www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/example/http/client/async_client.cpp . That should help.
If you see if handle_resolve is successful, it calls async_connect which will result in handle_connect to be fired. If handle_connect was called with no error, it writes some data to the connection (async_write) which in turn call async_read_until (on no error) which will fire handle_read_status_line, which may fire handle_read_headers, which may fire handle_read_content.
If you see there is no explicit disconnect as the destructor will do this internally.
Upvotes: 1