2011-01-19 148 views
9

这与this question有些相关,但我认为我需要多了解一点。我一直在试着让我的头脑几天(在其他部分工作的同时)如何做到这一点,但现在是时候让我咬紧牙关并获得多线程。而且,我比有关问题的信息多一点。boost :: asio,线程和同步

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

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

当我写我的主要应用,我猜这个解决方案是不能接受的(因为它会在消息循环中被调用哪个,虽然可能会有当消息队列阻塞等待消息时,你可以改变它,这样消息循环就不会阻塞,但是这不会阻止CPU使用率通过屋顶?)

解决方案它似乎是要抛出另一个线索。好的。但是当我没有工作要做时,我已经读了io_service::run()。那是什么?那是什么时候没有数据,或没有连接?如果至少有一个连接存在,它会保持活着吗?如果是这样,这不是什么大问题,因为我只需要在第一次连接时创建一个新线程,并且我很高兴如果一切都停止时就停止了。我想我对'没有工作要做'的定义感到困惑。

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

  1. 在客户端应用程序中使用boost :: asio关于线程并保持它们活着的最佳实践方式是什么?
  2. 当从主线程写入套接字到IO线程时,是否使用boost::asio::post实现同步,以便稍后在io_service中发生该调用?
  3. 当收到数据时,人们如何将数据返回到UI线程?在过去,当我使用完成端口时,我做了一个特殊的事件,可以使用:: SendMessage将数据发送回主UI线程。这不是优雅,但它的工作。

今天我会再读一些,但如果能够从已经完成这项工作的人那里得到正面评价,那将是一件好事。 Boost :: asio文档并不是很好,迄今为止我的大部分工作都是基于一些文档,一些试验/错误以及网络上的一些示例代码。

回答

6

1)看看io_service::work。只要工作对象存在,io_service :: run就不会返回。因此,如果您开始清理工作,请销毁工作对象,取消所有未完成的操作,例如套接字上的async_read,等待运行返回并清理资源。

2)io_service :: post将异步执行来自运行io_service的线程的给定处理程序。可以使用回调来获取执行操作的结果。

3)您需要某种形式的消息传递系统来通知您的GUI线程新数据。这里有几种可能性。

就你对文档的评论而言,我的Asio是一个更好记录的boost库,它附带清晰的例子。

+0

+1 io_service :: work是我自己解决这个问题的方法。 – 2011-01-19 13:31:59

+0

感谢您的回复。当你说有几种可能性时,过去你曾使用过什么? – 2011-01-19 14:11:11

1

boost::io_service::run()只有在没有任何操作时才会返回,因此没有异步操作正在等待,例如,异步接受/连接,异步读/写或异步定时器等待。所以在致电io_service::run()之前,您首先必须启动任何异步操作。

我还没有你有控制台或GUI应用程序?在任何情况下,多线程看起来都是过度的。您可以将Asio与消息循环一起使用。如果是win32 GUI,则可以从您的OnIdle()处理程序调用io_service :: run_one()。在控制台应用程序的情况下,您可以设置deadline_timer定期检查(每200毫秒?)用户输入,并与io_service::run()一起使用。一切都在单线程来大大简化解决方案

2

1)什么是客户端应用程序使用 提升 :: ASIO关于线程和保持 他们活着的最佳实践方法是什么?

随着documentation suggests,线程调用io_service::run池是最具可扩展性和最容易实现。

2)当从主 线程写入插座的IO线程,使用 的boost ::支持ASIO ::后 同步实现的,因此呼叫 在io_service对象后会发生什么?

您将需要使用a strand来保护可由多个线程调用的任何处理程序。见this answer,因为它可以帮助你,以及这个例子。

3)当收到数据时,人们如何将数据返回到UI线程?在 过去,当我使用完成端口, 我做了一个特殊的事件,可以发回 数据回到主UI线程 使用:: SendMessage。这不是 优雅,但它的工作。

怎么样,当你发布一个异步事件的io_serviceboost::function的形式提供的回调?然后事件的处理程序可以调用回调并用结果更新UI。

0

当收到数据后,人们如何将数据返回到UI线程?在过去,当我使用完成端口时,我做了一个特殊的事件,可以使用:: SendMessage将数据发送回主UI线程。这不是优雅,但它的工作

:: PostMessage可能更合适。

除非一切都在一个线程中运行,否则这些机制必须用于安全地将事件发布到UI线程。