À l'aide de boost::asio::io_service::post()
D'abord j'ai demandé à ce L'exécution d'une fonction sur le thread principal d'un coup de pouce fil et de la transmission de paramètres de la fonction d'
alors maintenant, je suis en train d'essayer ceci:
Ce qui suit est une console c++ projet où j'ai parfaitement simulé mon grand projet
TestServicePost.cpp
#include "stdafx.h"
#include "SomeClass.h"
int _tmain(int argc, _TCHAR* argv[])
{
SomeClass* s = new SomeClass();
while(true)
{
s->update();
}
return 0;
}
SomeClass.h
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <queue>
class ServiceNote
{
public:
std::string getType()
{
std::stringstream typeSS;
typeSS << "LamasaTech.MultiWall.PostNote." << (NoteType.compare("Normal") == 0 ? "Node" : "Header") << "." << Shape << "." << Colour;
return typeSS.str();
}
int Action;
int CNoteId;
std::string Colour;
int NoteId;
std::string NoteType;
int SessionId;
std::string Shape;
std::string Style;
std::string Text;
int X;
int Y;
};
class SomeClass
{
public:
SomeClass();
~SomeClass();
void update();
private:
std::queue<ServiceNote> pendingNotes;
void addToQueue(ServiceNote sn);
void pollService(boost::asio::io_service* svc);
int getMessage(boost::asio::io_service* svc, std::string sessionId, int messageId);
boost::thread servicePoller;
};
SomeClass.cpp
#include "stdafx.h"
#include "SomeClass.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/asio/signal_set.hpp>
#define POLL_SERVICE = 0;
#define POLLING_WAIT_TIME 1000
#define SAVE_SESSION_EVERY 1800000
SomeClass::SomeClass()
{
boost::asio::io_service io_servicePoller;
io_servicePoller.run();
servicePoller = boost::thread(boost::bind(&SomeClass::pollService, this, &io_servicePoller));
/*boost::asio::io_service io_sessionSaver;
boost::asio::signal_set signalsSaver(io_sessionSaver, SIGINT, SIGTERM);
signalsSaver.async_wait( boost::bind(&boost::asio::io_service::stop, &io_sessionSaver));
sessionSaver = boost::thread(&SomeClass::saveSessionEvery, io_sessionSaver);*/
}
SomeClass::~SomeClass()
{
}
void SomeClass::update()
{
while(!pendingNotes.empty())
{
ServiceNote sn = pendingNotes.front();
pendingNotes.pop();
}
}
void SomeClass::addToQueue(ServiceNote sn)
{
pendingNotes.push(sn);
}
void SomeClass::pollService(boost::asio::io_service* svc)
{
int messageId = 1;
while(true)
{
if(boost::this_thread::interruption_enabled() && boost::this_thread::interruption_requested())
return;
int currentId = messageId;
messageId = getMessage(svc, "49", messageId);
if(currentId == messageId)
boost::this_thread::sleep(boost::posix_time::milliseconds(POLLING_WAIT_TIME));
}
}
int SomeClass::getMessage(boost::asio::io_service* svc, std::string sessionId, int messageId)
{
try
{
boost::asio::io_service io_service;
//Get a list of endpoints corresponding to the server name.
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query("mw.rombus.com", "http");
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
//Try each endpoint until we successfully establish a connection.
boost::asio::ip::tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
//Form the request. We specify the "Connection: close" header so that the
//server will close the socket after transmitting the response. This will
//allow us to treat all data up until the EOF as the content.
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " "/Service.svc/message/" << sessionId << "/" << messageId << " HTTP/1.0\r\n";
request_stream << "Host: " << "mw.rombus.com" << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
//Send the request.
boost::asio::write(socket, request);
//Read the response status line. The response streambuf will automatically
//grow to accommodate the entire line. The growth may be limited by passing
//a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
//Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
//std::cout << "Invalid response\n";
return messageId;
}
if (status_code != 200)
{
//std::cout << "Response returned with status code " << status_code << "\n";
return messageId;
}
//Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");
//Process the response headers.
std::string header;
std::string fullHeader = "";
while (std::getline(response_stream, header) && header != "\r")
fullHeader.append(header).append("\n");
//Write whatever content we already have to output.
std::string fullResponse = "";
if (response.size() > 0)
{
std::stringstream ss;
ss << &response;
fullResponse = ss.str();
try
{
boost::property_tree::ptree pt;
boost::property_tree::read_json(ss, pt);
ServiceNote sn;
sn.Action = pt.get<int>("Action");
sn.CNoteId = pt.get<int>("CNoteId");
sn.Colour = pt.get<std::string>("Colour");
sn.NoteId = pt.get<int>("NoteId");
sn.NoteType = pt.get<std::string>("NoteType");
sn.SessionId = pt.get<int>("SessionId");
sn.Shape = pt.get<std::string>("Shape");
sn.Style = pt.get<std::string>("Style");
sn.Text = pt.get<std::string>("Text");
sn.X = pt.get<int>("X");
sn.Y = pt.get<int>("Y");
svc->post(boost::bind(&SomeClass::addToQueue, this, sn));
//pendingNotes.push(sn);
}
catch (std::exception const& e)
{
std::string test = e.what();
//std::cerr << e.what() << std::endl;
}
messageId++;
}
//Read until EOF, writing data to output as we go.
std::string fullSth = "";
boost::system::error_code error;
while (boost::asio::read(socket, response,
boost::asio::transfer_at_least(1), error))
{
std::ostringstream ss;
ss << &response;
fullSth = ss.str();
}
if (error != boost::asio::error::eof)
throw boost::system::system_error(error);
}
catch (std::exception& e)
{
std::string test = e.what();
std::cout << "Exception: " << e.what() << "\n";
}
return messageId;
}
mais je reçois Unhandled exception at 0x771215de in TestServicePost.exe: 0xC0000005: Access violation writing location 0xcccccce4.
, juste après cette ligne s'exécute:
svc->post(boost::bind(&SomeClass::addToQueue, this, sn));
Je n'arrivais pas à définir io_service en tant que membre de la classe donc je peux l'utiliser dans le destructeur ~SomeClass()
, serait heureux d'aider sur ce que trop
Si io_service.post n'est pas la meilleure solution pour moi s'il vous plaît recommander quelque chose, comme vous pouvez le voir, j'ai un constructeur, un destructeur et une mise à jour de la méthode qui est appelée à chaque tick, j'ai essayé d'utiliser ce et la file d'attente seuls, mais il n'est pas thread-safe, est-il facile thread-safe FIFO à utiliser ?
OriginalL'auteur Shereef Marzouk | 2012-12-09
Vous devez vous connecter pour publier un commentaire.
Dans
SomeClass
constructeur effectuer les opérations suivantes:io_service
instance.run()
états-fonction, qui retourne immédiatement, parce que io_service n'a pas de travail.Ce ne sera certainement pas de travail.
Noter que
io_service::run()
est une sorte de "boucle de message", donc il doit bloquer le thread appelant. Ne l'appelez pas dans le constructeur de l'objet.Merci, j'ai corrigé, je vais poster ma solution maintenant 🙂
faire un autre membre de la fonction, donner
io_service
certainswork
, et d'appelerrun
que la dernière instruction (il va bloquer):void run() { io_service io_servicePoller; io_service::work work(io_servicePoller); servicePoller = thread(bind(&SomeClass::pollService, this, &io_servicePoller)); io_servicePoller.run(); }
Je ne comprends pas ce que vous avez écrit, mais j'ai posté la solution que j'ai mis en œuvre
OriginalL'auteur Igor R.
J'ai compris comment déclarer io_service en tant que membre de la classe:
et dans le constructeur, je n'ai suivantes:
Nettoyage
et dans la mise à jour, j'ai appelé exécuter ce qui ajoute de la substance dans la file d'attente, puis les lit dans la boucle while
et changé mes membres de la signature de
void SomeClass::pollService(boost::shared_ptr< boost::asio::io_service > svc)
Ce qui se passe est:
Grâce à Igor R. je ne pouvais pas le faire sans lui
et aussi http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=4 où j'ai trouvé la façon de faire le pointeur partagé
io_service::run()
de cette façon (c'est à dire de ne traiter que les éléments actuellement disponibles dans io_service file d'attente et de sortie), vous devez appelerio_servicePoller->reset()
avant -- sinonrun
ne fonctionne que pour la 1ère fois.Il fonctionne très bien, à chaque fois
Mais j'ai ajouté io_servicePoller->reset(); après io_servicePoller->run(); de toute façon, parce que je vous respecte et je suis sûr que vous êtes plus expérimenté puis m'
OriginalL'auteur Shereef Marzouk