这与this question有些相关,但我想我需要多了解一点。我一直试图让我的头脑在几天内完成这项工作(同时处理其他部分),但现在是时候咬紧牙关并获得多线程了。此外,我提供的信息比链接的问题要多一些。
首先,关于多线程。因为我一直在测试我的代码,所以我没有烦恼任何多线程。它只是一个控制台应用程序,它启动与测试服务器的连接,然后处理其他所有内容。主循环是:
while(true)
{
Root::instance().performIO(); // calls io_service::runOne();
}
当我编写我的主应用程序时,我猜这个解决方案是不可接受的(因为它必须在消息循环中调用,尽管可能在消息队列阻塞等待消息时会出现问题你可以改变它,以便消息循环不会阻塞,但那不会打破通过屋顶的CPU使用率吗?)
似乎解决方案就是抛出另一个线程。好的。但后来我读到io_service::run()
在没有工作要做的时候会返回。那是什么?那是没有数据,还是没有连接?如果至少存在一个连接,它是否仍然存活?如果是这样,那就不是问题了,因为我只需要在第一次连接时启动一个新线程,如果在没有任何事情发生时全部停止,我很高兴。我想我对'无工作'的定义感到困惑。
然后我不得不担心将我的boost线程与我的主GUI线程同步。所以,我想我的问题是:
boost::asio::post
实现了同步,以便稍后在io_service中进行调用?今天我会再读一些,但是从已经做过这件事的人那里得到一个很好的帮助会很棒。 Boost :: asio文档并不是很好,到目前为止我的大部分工作都是基于一些文档,一些试验/错误,网上的一些示例代码。
答案 0 :(得分:6)
1)看看io_service::work。只要工作对象存在,io_service :: run就不会返回。因此,如果您开始清理,请销毁工作对象,取消所有未完成的操作,例如套接字上的async_read,等待run返回并清理资源。
2)io_service :: post将从运行io_service的线程异步执行给定的处理程序。回调可用于获取执行操作的结果。
3)您需要某种形式的消息传递系统来通知您的GUI线程新数据。这里有几种可能性。
至于你对文档的评论,我认为Asio是更好的文档提升库之一,它带有明显的例子。
答案 1 :(得分:2)
1)使用的最佳实践方法是什么 客户端应用程序中的boost :: asio 关于线程和保持 他们活着吗?
作为documentation suggests,调用io_service::run
的线程池是最具可扩展性且最容易实现的。
2)从主要写入套接字时 线程到IO线程,是 同步实现使用 boost :: asio :: post,以便调用 稍后会在io_service中发生吗?
您需要使用a strand来保护多个线程可以调用的任何处理程序。请参阅this answer,因为它可能对您有所帮助,以及此示例。
3)收到数据后,人们怎么做 将数据恢复到UI线程?在 我使用完成端口时的过去, 我做了一个可以发布的特别活动 数据回到主UI线程 使用:: SendMessage。事实并非如此 优雅,但它有效。
当您向boost::function
发布异步事件时,如何以io_service
的形式提供回调?然后事件的处理程序可以调用回调并使用结果更新UI。
答案 2 :(得分:1)
boost::io_service::run()
仅在没有任何操作时返回,因此没有异步操作待处理,例如异步接受/连接,异步读/写或异步定时器等待。所以在调用io_service::run()
之前,首先必须启动任何异步操作。
我没有你有控制台或GUI应用程序吗?无论如何,多线程看起来像是一种矫枉过正。您可以将Asio与消息循环结合使用。如果它是win32 GUI,你可以从你的OnIdle()处理程序调用io_service :: run_one()。在控制台应用程序的情况下,您可以设置deadline_timer
定期检查(每200毫秒?)用户输入并与io_service::run()
一起使用。单线程中的所有内容都大大简化了解决方案
答案 3 :(得分:0)
收到数据后,人们如何将数据恢复到UI线程?在过去,当我使用完成端口时,我做了一个特殊事件,可以使用:: SendMessage将数据发布回主UI线程。它不优雅,但它起作用了
:: PostMessage可能更合适。
除非一切都在一个线程中运行,否则必须使用这些机制将事件安全地发布到UI线程。