У меня есть простой код, использующий boost.asio, например следующий:
namespace net = boost::asio;
int main()
{
net::io_context ioContext;
AsyncClass myClass(ioContext);
myClass.onAsyncEvent1([] { /* do stuff */ })
myClass.onAsyncEvent2([] { /* do stuff */ });
ioContext.run();
return 0;
}
Я хочу добавить этот код в приложение GUI (Android / Linux / Windows) .
Решения, которые я нашел в сети, очень неэффективны для меня. Наиболее распространенными являются:
- с таймером GUI и вызовом оттуда функции
poll_one
. - Использование опроса:
- Проверьте, получено ли сообщение от GUI и обработайте его, если будет
- вызов
poll_one
- сумма сна
Но эти два решения просто сохраняют Высокая загрузка ЦП для того, чтобы ничего не делать, а на мобильном телефоне это просто означает бесполезную трату масла.
ЧТО Я ХОЧУ
Я хотел бы заблокировать все, пока что-то не произойдет, и справиться все события asyn c в основном потоке GUI
namespace net = boost::asio;
int main()
{
net::io_context ioContext;
AsyncClass myClass(ioContext);
// gui code
myClass.onAsyncEvent1([] { /* update gui */ });
myClass.onAsyncEvent2([] { /* update gui */ });
thread asyncThread{[&ioContext] {
ioContext.wait();
// this is blocking until the message is done
sendMessageToGUI(GUI_CUSTOM_EVENT);
}
while(true)
{
GUIEvent event;
// this is blocking
GetMessage(event);
if (event == GUI_CUSTOM_EVENT)
ioContext.run_one(); // run_one or poll_one are the same here
}
return 0;
}
К сожалению, Boost.Asio не предоставляет такой утилиты ...
ВОПРОСЫ
- Почему такая функция не реализована в Boost? Или, может быть, Boost.Asio просто не подходит для асин c кода в GUI приложениях
- Это неправильный метод? Может быть, умнее способ сделать это.
ВОЗМОЖНОЕ РЕШЕНИЕ?
Возможное решение может просто вызвать sendMessageToGUI
из обратного вызова ...
namespace net = boost::asio;
int main()
{
net::io_context ioContext, guiContext;
AsyncClass myClass(ioContext);
// non gui code
myClass.onAsyncEvent1([] { /* do stuff */ });
myClass.onAsyncEvent2([] { /* do stuff */ });
myClass.onAsyncEvent3([] { /* do stuff */ });
myClass.onAsyncEvent4([] { /* do stuff */ });
// gui code
myClass.onAsyncEvent1([&guiContext]
{
postGUIMessage(GUI_CUSTOM_MESSAGE);
guiContext.post([]{
// this will unlock the main thread
ui->laber->setText("yes!");
}
});
myClass.onAsyncEvent4([&guiContext]
{
postGUIMessage(GUI_CUSTOM_MESSAGE);
guiContext.post([]{
// this will unlock the main thread
ui->laber->setText("yes!");
}
});
thread_pool.enqueue{[&ioContext] { ioContext.run(); }
while(true)
{
GUIEvent event;
// this is blocking
GetMessage(event);
if (event == GUI_CUSTOM_EVENT)
guiContext.poll();
return 0;
}
Преимущество заключается в том, что я могу справиться с преимуществами многоядерных и перенаправлять только GUI события ...