- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想使用用于 GUI 的线程和用于某些套接字 IO 的工作线程来实现 Boost Asio 模式。
工作线程将使用boost::asio::io_service
来管理套接字客户端。套接字上的所有操作将仅由工作线程执行。
GUI 线程需要从工作线程发送和接收消息。
我不知道如何使用 Boost Asio 实现这种模式。
我已经以标准的 Asio 方式实现了套接字通信(我从工作线程调用 io_service.run()
并使用 async_read_some
/异步发送
)。我不需要 strands
,因为 io_service.run()
仅从工作线程调用。
现在我正在尝试添加跨线程消息队列。我该如何实现?
我是否也应该从 GUI 线程运行
io_service
?
或者我应该只使用 strands
和 post
将消息从 GUI 线程发布到工作线程(而不调用 io_service.run()
或来自 GUI 线程的 io_service.poll_one()
),并使用操作系统的 GUI 消息循环将消息从工作线程发布到 GUI 线程?
如果我也需要从 GUI 线程调用 io_service.run()
或 io_service.poll_one()
,我是否需要使用 strands
在套接字操作上,因为 io_service
在两个线程之间共享?
编辑:为了澄清我的问题,我想尽我所能,使用 Boost Asio 实现消息队列,仅当 Boost Asio 无法完成这项工作时才依赖其他库。
最佳答案
消息传递相当通用。解决问题的方法多种多样,解决方案可能取决于所需的行为细节。例如,阻塞或非阻塞、控制内存分配、上下文等。
Boost.Lockfree为单个/多个消费者/生产者提供线程安全的无锁非阻塞队列。它往往非常适合事件循环,在这种情况下,阻塞消费者、等待生产者发出同步构造信号并不理想。
boost::lockfree::queue<message_type> worker_message_queue;
void send_worker_message(const message_type& message)
{
// Add message to worker message queue.
worker_message_queue.push(message);
// Add work to worker_io_service that will process the queue.
worker_io_service.post(&process_message);
}
void process_message()
{
message_type message;
// If the message was not retrieved, then return early.
if (!worker_message_queue.pop(message)) return;
...
}
或者,Boost.Asio的 io_service
可以充当队列。消息只需要绑定(bind)到指定的处理程序即可。
void send_worker_message(const message_type& message)
{
// Add work to worker_io_service that will process the message.
worker_io_service.post(boost::bind(&process_message, message));
}
void process_message(message_type& message)
{
...
}
This评论表明,愿望不仅仅是传递信息。听起来好像最终目标是允许一个线程导致另一个线程调用任意函数。
如果是这种情况,请考虑:
io_service
设置信号发射。如果 GUI 线程和工作线程都有自己的 io_service
,那么工作线程可以将处理程序发布到 GUI 线程的 io_service
中,该处理程序将发出信号。在 GUI 线程的主循环中,它将轮询 io_service
,发出信号,并导致从 GUI 线程的上下文中调用插槽。这是一个完整的示例,其中两个线程将一条消息(作为 unsigned int
)相互传递,并导致在另一个线程中调用任意函数。
#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/signals2.hpp>
#include <boost/thread.hpp>
/// @brief io_service dedicated to gui.
boost::asio::io_service gui_service;
/// @brief io_service dedicated to worker.
boost::asio::io_service worker_service;
/// @brief work to keep gui_service from stopping prematurely.
boost::optional<boost::asio::io_service::work> gui_work;
/// @brief hello slot.
void hello(int x)
{
std::cout << "hello with " << x << " from thread " <<
boost::this_thread::get_id() << std::endl;
}
/// @brief world slot.
void world(int x)
{
std::cout << "world with " << x << " from thread " <<
boost::this_thread::get_id() << std::endl;
}
/// @brief Type for signals.
typedef boost::signals2::signal<void (int)> signal_type;
void emit_then_notify_gui(signal_type& signal, unsigned int x);
/// @brief Emit signals then message worker.
void emit_then_notify_worker(signal_type& signal, unsigned int x)
{
// Emit signal, causing registered slots to run within this thread.
signal(x);
// If x has been exhausted, then cause gui service to run out of work.
if (!x)
{
gui_work = boost::none;
}
// Otherwise, post work into worker service.
else
{
std::cout << "GUI thread: " << boost::this_thread::get_id() <<
" scheduling other thread to emit signals" << std::endl;
worker_service.post(boost::bind(
&emit_then_notify_gui,
boost::ref(signal), --x));
}
}
/// @brief Emit signals then message worker.
void emit_then_notify_gui(signal_type& signal, unsigned int x)
{
// Emit signal, causing registered slots to run within this thread.
signal(x);
// If x has been exhausted, then cause gui service to run out of work.
if (!x)
{
gui_work = boost::none;
}
// Otherwise, post more work into gui.
else
{
std::cout << "Worker thread: " << boost::this_thread::get_id() <<
" scheduling other thread to emit signals" << std::endl;
gui_service.post(boost::bind(
&emit_then_notify_worker,
boost::ref(signal), --x));
}
}
void worker_main()
{
std::cout << "Worker thread: " << boost::this_thread::get_id() << std::endl;
worker_service.run();
}
int main()
{
signal_type signal;
// Connect slots to signal.
signal.connect(&hello);
signal.connect(&world);
boost::optional<boost::asio::io_service::work> worker_work(
boost::ref(worker_service));
gui_work = boost::in_place(boost::ref(gui_service));
std::cout << "GUI thread: " << boost::this_thread::get_id() << std::endl;
// Spawn off worker thread.
boost::thread worker_thread(&worker_main);
// Add work to worker.
worker_service.post(boost::bind(
&emit_then_notify_gui,
boost::ref(signal), 3));
// Mocked up GUI main loop.
while (!gui_service.stopped())
{
// Do other GUI actions.
// Perform message processing.
gui_service.poll_one();
}
// Cleanup.
worker_work = boost::none;
worker_thread.join();
}
及其输出:
GUI thread: b7f2f6d0Worker thread: b7f2eb90hello with 3 from thread b7f2eb90world with 3 from thread b7f2eb90Worker thread: b7f2eb90 scheduling other thread to emit signalshello with 2 from thread b7f2f6d0world with 2 from thread b7f2f6d0GUI thread: b7f2f6d0 scheduling other thread to emit signalshello with 1 from thread b7f2eb90world with 1 from thread b7f2eb90Worker thread: b7f2eb90 scheduling other thread to emit signalshello with 0 from thread b7f2f6d0world with 0 from thread b7f2f6d0
关于c++ - 使用 GUI 和工作线程提升 Asio 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17976568/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!