Дополнительный поток (ы) для обработки обратного вызова - хорошая идея. Как упоминалось выше, обратный вызов помещает сообщение в потокобезопасную очередь, а другой поток, потребляющий / обрабатывающий сообщение, прекрасно работает.
Еще один сценарий с многопоточностью, который может вам помочь, - это просто запустить дополнительные потоки на io_service. Эти дополнительные потоки позволят обрабатывать несколько обработчиков одновременно.
const int max_threads = 5;
boost::asio::io_service ios;
boost::thread_group thread_group;
for (int i = 0 ; i < max_threads; ++i)
thread_group.create_thread( boost::bind(&boost::asio::io_service::run, boost::ref(ios)) );
Правильное решение действительно зависит от того, что делает приложение. Если это TCP-соединение и сообщения должны обрабатываться в последовательном порядке, рассмотрите возможность использования очереди производителя / потребителя. Если сообщения независимы друг от друга и не требуют, чтобы они обрабатывались по порядку, тогда этот подход также подходит.
Если это соединение UDP, то все ставки в любом случае отключены, потому что порядок принятых сообщений не гарантируется.