Aslında birkaç seçeneğiniz var. Sen seri bağlantı noktasının yerleşik async_read_some
işlevini kullanabilirsiniz veya takvimi tek başına işlev boost::asio::async_read
(veya async_read_some
) kullanabilir.
(1) veri okumak veya (2) bir hata oluşursa sürece bunların hiçbiri geri arama arayacak beri Hala etkili olan durum "bloke" içine edeceğiz. Bunu aşmak için, bir zaman aşımı ayarlamak üzere deadline_timer
nesnesini kullanmak istersiniz. Zaman aşımı önce patlarsa, veri mevcut değildi. Aksi takdirde, okumanız olacak.
Eklenen karmaşıklık gerçekten de o kadar da kötü değil. Benzer davranışa sahip iki geri arama ile sonuçlanacaksınız. "Okumak" veya "zaman aşımı" geri çağırma bir hata ile ateş ederse, bunun yarış kaybeden olduğunu bilirsiniz. Eğer biri hata yapmadan ateş ederse, o zaman yarış kazananı olduğunu bilirsiniz (ve diğer aramayı iptal etmelisiniz). read_some
numaralı telefona engelleme yaptığınız yerde, şimdi io_svc.run()
numaralı telefonu arayacaksınız. İşleviniz, run
numaralı telefonu çağırdığında olduğu gibi engellenir, ancak bu kez süreyi denetlersiniz. Eğer belirli ihtiyaçlarını karşılamak için orada burada sadece birkaç tweaks ile başlamak gerekir
void foo()
{
io_service io_svc;
serial_port ser_port(io_svc, "your string here");
deadline_timer timeout(io_svc);
unsigned char my_buffer[1];
bool data_available = false;
ser_port.async_read_some(boost::asio::buffer(my_buffer),
boost::bind(&read_callback, boost::ref(data_available), boost::ref(timeout),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
timeout.expires_from_now(boost::posix_time::milliseconds(<<your_timeout_here>>));
timeout.async_wait(boost::bind(&wait_callback, boost::ref(ser_port),
boost::asio::placeholders::error));
io_svc.run(); // will block until async callbacks are finished
if (!data_available)
{
kick_start_the_device();
}
}
void read_callback(bool& data_available, deadline_timer& timeout, const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (error || !bytes_transferred)
{
// No data was read!
data_available = false;
return;
}
timeout.cancel(); // will cause wait_callback to fire with an error
data_available = true;
}
void wait_callback(serial_port& ser_port, const boost::system::error_code& error)
{
if (error)
{
// Data was read and this timeout was canceled
return;
}
ser_port.cancel(); // will cause read_callback to fire with an error
}
:
İşte bir örnek. Umarım bu yardımcı olur!
başka not: İlave ipler geri aramalar işlemek için gerekliydi. Her şey run()
numaralı çağrı ile ele alınır. ... Zaten bunun farkında olsaydı emin değil
Bu yaklaşımı kullandım ve iyi çalışıyor, ancak yalnızca ilk kez. Bir sonraki io_svc.run() çağrısı hemen döner. Fazladan bir şey yapmam gerekecek mi? Teşekkür – Schiavini
görünüşte io_svc.run() sonra io_svc.reset() aramak zorunda kaldı. – Schiavini
büyük cevap, çok yararlı. Ancak, bazı garip davranışlar alıyorum: Seri portuna her 5 ms'de bir veri yazma ve başka bir okuma dizisinden veri yazma programım var, ancak eğer okuyucunun gecikme süresini 5 ms'ye ayarladıysam, hala "veri kullanılamıyor" oluyor okunan değerler ile karışık aramalar.Bu, koddaki bazı ek yüklerden mi kaynaklanıyor yoksa bir şeyleri mi özlüyorum? – joaocandre