简体   繁体   English

boost :: asio,线程和同步

[英]boost::asio, threads and synchronization

This is somewhat related to this question , but I think I need to know a little bit more. 这与这个问题有些相关,但我想我需要多了解一点。 I've been trying to get my head around how to do this for a few days (whilst working on other parts), but the time has come for me to bite the bullet and get multi-threaded. 我一直试图让我的头脑在几天内完成这项工作(同时处理其他部分),但现在是时候咬紧牙关并获得多线程了。 Also, I'm after a bit more information than the question linked. 另外,我提供的信息比链接的问题要多一些。

Firstly, about multi-threading. 首先,关于多线程。 As I have been testing my code, I've not bothered with any multi-threading. 因为我一直在测试我的代码,所以我没有烦恼任何多线程。 It's just a console application that starts a connection to a test server and everything else is then handled. 它只是一个控制台应用程序,它启动与测试服务器的连接,然后处理其他所有内容。 The main loop is this: 主循环是这样的:

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

When I write my main application, I'm guessing this solution won't be acceptable (as it would have to be called in the message loop which, whilst possible, would have issues when the message queue blocks waiting for a message. You could change it so that the message-loop doesn't block, but then isn't that going to whack the CPU usage through the roof?) 当我编写我的主应用程序时,我猜这个解决方案是不可接受的(因为它必须在消息循环中调用,尽管可能,当消息队列阻塞等待消息时会出现问题。你可以更改它,以便消息循环不会阻止,但那不会打破通过屋顶的CPU使用率吗?)

The solution it seems is to throw another thread at it. 似乎解决方案是抛出另一个线程。 Okay, fine. 好的。 But then I've read that io_service::run() returns when there is no work to do. 但后来我发现当没有工作要做时, io_service::run()返回。 What is that? 那是什么? Is that when there's no data, or no connections? 那是没有数据,还是没有连接? If at least one connection exists does it stay alive? 如果至少存在一个连接,它是否仍然存活? If so, that's not so much of a problem as I only have to start up a new thread when the first connection is made and I'm happy if it all stops when there is nothing going on at all. 如果是这样,那就不是问题了,因为我只需要在第一次连接时启动一个新线程,如果在没有任何事情发生时全部停止,我很高兴。 I guess I am confused by the definition of 'no work to do'. 我想我对“没有工作要做”的定义感到困惑。

Then I have to worry about synchronizing my boost thread with my main GUI thread. 然后我不得不担心我的boost线程与我的主GUI线程同步。 So, I guess my questions are: 所以,我想我的问题是:

  1. What is the best-practice way of using boost::asio in a client application with regard to threads and keeping them alive? 在客户端应用程序中使用boost :: asio关于线程并保持它们活着的最佳实践方法是什么?
  2. When writing to a socket from the main thread to the IO thread, is synchronization achieved using boost::asio::post , so that the call happens later in the io_service? 当从主线程写入套接字到IO线程时,使用boost::asio::post实现同步,以便稍后在io_service中调用?
  3. When data is received, how do people get the data back to the UI thread? 收到数据后,人们如何将数据恢复到UI线程? In the past when I used completion ports, I made a special event that could post the data back to the main UI thread using a ::SendMessage. 在过去,当我使用完成端口时,我做了一个特殊事件,可以使用:: SendMessage将数据发布回主UI线程。 It wasn't elegant, but it worked. 它不优雅,但它起作用。

I'll be reading some more today, but it would be great to get a heads up from someone who has done this already. 今天我会再读一些,但是从已经做过这件事的人那里得到一个很好的帮助会很棒。 The Boost::asio documentation isn't great, and most of my work so far has been based on a bit of the documentation, some trial/error, some example code on the web. Boost :: asio文档并不是很好,到目前为止我的大部分工作都是基于一些文档,一些试验/错误,网上的一些示例代码。

1) Have a look at io_service::work . 1)看看io_service :: work As long as an work object exists io_service::run will not return. 只要工作对象存在,io_service :: run就不会返回。 So if you start doing your clean up, destroy the work object, cancel any outstanding operations, for example an async_read on a socket, wait for run to return and clean up your resources. 因此,如果您开始清理,请销毁工作对象,取消所有未完成的操作,例如套接字上的async_read,等待run返回并清理资源。

2) io_service::post will asynchronously execute the given handler from a thread running the io_service. 2)io_service :: post将从运行io_service的线程异步执行给定的处理程序。 A callback can be used to get the result of the operation executed. 回调可用于获取执行操作的结果。

3) You needs some form of messaging system to inform your GUI thread of the new data. 3)您需要某种形式的消息传递系统来通知您的GUI线程新数据。 There are several possibilities here. 这里有几种可能性。

As far as your remark about the documention, I thing Asio is one of the better documented boost libraries and it comes with clear examples. 至于你对这个文档的评论,我的东西Asio是更好的文档提升库之一,它带有明确的例子。

boost::io_service::run() will return only when there's nothing to do, so no async operations are pending, eg async accept/connection, async read/write or async timer wait. boost::io_service::run()仅在没有任何操作时返回,因此没有异步操作挂起,例如异步接受/连接,异步读/写或异步定时器等待。 so before calling io_service::run() you first have to start any async op. 所以在调用io_service::run() ,首先必须启动任何异步操作。

i haven't got do you have console or GUI app? 我没有你有控制台或GUI应用程序吗? in any case multithreading looks like a overkill. 无论如何,多线程看起来像是一种矫枉过正。 you can use Asio in conjunction with your message loop. 您可以将Asio与消息循环结合使用。 if it's win32 GUI you can call io_service::run_one() from you OnIdle() handler. 如果它是win32 GUI,你可以从你的OnIdle()处理程序调用io_service :: run_one()。 in case of console application you can setup deadline_timer that regularly checks (every 200ms?) for user input and use it with io_service::run() . 在控制台应用程序的情况下,您可以设置deadline_timer定期检查(每200ms?)用户输入并使用io_service::run() everything in single thread to greatly simplify the solution 单线程中的一切都大大简化了解决方案

1) What is the best-practice way of using boost::asio in a client application with regard to threads and keeping them alive? 1)在客户端应用程序中使用boost :: asio关于线程并使它们保持活动状态的最佳实践方法是什么?

As the documentation suggests , a pool of threads invoking io_service::run is the most scalable and easiest to implement. 正如文档所示 ,调用io_service::run的线程池是最具可伸缩性和最容易实现的。

2) When writing to a socket from the main thread to the IO thread, is synchronization achieved using boost::asio::post, so that the call happens later in the io_service? 2)当从主线程写入套接字到IO线程时,是否使用boost :: asio :: post实现同步,以便稍后在io_service中调用?

You will need to use a strand to protect any handlers that can be invoked by multiple threads. 您将需要使用strand来保护可由多个线程调用的任何处理程序。 See this answer as it may help you, as well as this example. 请参阅此答案,因为它可能会对您有所帮助,以及此示例。

3) When data is received, how do people get the data back to the UI thread? 3)收到数据后,人们如何将数据恢复到UI线程? In the past when I used completion ports, I made a special event that could post the data back to the main UI thread using a ::SendMessage. 在过去,当我使用完成端口时,我做了一个特殊事件,可以使用:: SendMessage将数据发布回主UI线程。 It wasn't elegant, but it worked. 它不优雅,但它起作用。

How about providing a callback in the form of a boost::function when you post an asynchronous event to the io_service ? 当您向io_service发布异步事件时,如何以boost::function的形式提供回调? Then the event's handler can invoke the callback and update the UI with the results. 然后事件的处理程序可以调用回调并使用结果更新UI。

When data is received, how do people get the data back to the UI thread? 收到数据后,人们如何将数据恢复到UI线程? In the past when I used completion ports, I made a special event that could post the data back to the main UI thread using a ::SendMessage. 在过去,当我使用完成端口时,我做了一个特殊事件,可以使用:: SendMessage将数据发布回主UI线程。 It wasn't elegant, but it worked 它不优雅,但它起作用

::PostMessage may be more appropriate. :: PostMessage可能更合适。

Unless everything runs in one thread these mechanisms must be used to safely post events to the UI thread. 除非一切都在一个线程中运行,否则必须使用这些机制将事件安全地发布到UI线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM