boost :: asio,线程和同步

时间:2011-01-19 11:03:14

标签: c++ boost boost-asio

这与this question有些相关,但我想我需要多了解一点。我一直试图让我的头脑在几天内完成这项工作(同时处理其他部分),但现在是时候咬紧牙关并获得多线程了。此外,我提供的信息比链接的问题要多一些。

首先,关于多线程。因为我一直在测试我的代码,所以我没有烦恼任何多线程。它只是一个控制台应用程序,它启动与测试服务器的连接,然后处理其他所有内容。主循环是:

while(true)
{
    Root::instance().performIO(); // calls io_service::runOne();
}

当我编写我的主应用程序时,我猜这个解决方案是不可接受的(因为它必须在消息循环中调用,尽管可能在消息队列阻塞等待消息时会出现问题你可以改变它,以便消息循环不会阻塞,但那不会打破通过屋顶的CPU使用率吗?)

似乎解决方案就是抛出另一个线程。好的。但后来我读到io_service::run()在没有工作要做的时候会返回。那是什么?那是没有数据,还是没有连接?如果至少存在一个连接,它是否仍然存活?如果是这样,那就不是问题了,因为我只需要在第一次连接时启动一个新线程,如果在没有任何事情发生时全部停止,我很高兴。我想我对'无工作'的定义感到困惑。

然后我不得不担心将我的boost线程与我的主GUI线程同步。所以,我想我的问题是:

  1. 在客户端应用程序中使用boost :: asio关于线程并保持它们活着的最佳实践方法是什么?
  2. 当从主线程写入套接字到IO线程时,是否使用boost::asio::post实现了同步,以便稍后在io_service中进行调用?
  3. 收到数据后,人们如何将数据恢复到UI线程?在过去,当我使用完成端口时,我做了一个特殊事件,可以使用:: SendMessage将数据发布回主UI线程。它并不优雅,但它确实有效。
  4. 今天我会再读一些,但是从已经做过这件事的人那里得到一个很好的帮助会很棒。 Boost :: asio文档并不是很好,到目前为止我的大部分工作都是基于一些文档,一些试验/错误,网上的一些示例代码。

4 个答案:

答案 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线程。