异步完成处理
我有这种情况:异步完成处理
void foo::bar()
{
RequestsManager->SendRequest(someRequest, this, &foo::someCallback);
}
其中RequestsManager工作在异步方式:
- sendRequest将放在一个队列并返回给调用者
- 其他线程获取请求来自队列的请求并处理它们
- 当处理一个请求时,回调被称为
是否有可能在与SendRequest相同的线程中调用foo :: someCallback?如果没有,我怎么能避免“回调限制”:回调不应该做耗时的操作,以避免阻止请求管理器。
我可以看到一些方法如何实现它:
A)实施类似于信号处理的策略
当请求处理结束时RequestManager
将回调调用置于等待列表上。下次调用SendRequest
时,在返回执行之前,它会检查线程是否有未决的回调并执行它们。这是相对简单的方法,对客户端的要求最低。如果延迟不是问题,请选择它。 RequestManager
可以公开API强行检查挂起回调
B)挂起回调目标线程,并在第三线程执行回调
这会给你所有的告诫真正异步解决方案。它看起来像是目标线程执行被中断,执行跳入中断处理程序。在回调之前,目标线程需要被恢复。您将无法从回调内部访问线程本地存储或原始线程的堆栈。
否 - 调用/回调不能更改线程上下文 - 您必须发出一些信号以在线程之间进行通信。通常情况下,'someCallback'会或者发出发起'SendRequest'调用的线程正在等待的事件,(同步调用)或者推送SendRequest,(因此,可能是它的处理结果)到发送'SendRequest'调用的线程最终会弹出的队列上(异步)。这取决于发信人的信号是如何闪烁的。
Aynch示例 - 回调可能PostMessage/Dispatcher.Begin将完成的SendRequest调用到GUI线程以显示结果。
取决于“耗时操作”的定义。
经典的方式做到这一点是:
- 在处理请求,
RequestManager
应该执行该&foo::someCallback
- 避免阻塞请求管理器,你可能只是上升这里面的标志回调
- 检查标志周期性的线程内,这被称为
RequestsManager->SendRequest
- 此标志将只是一个
volatile bool
内class foo
如果你想确保,调用线程(foo
的)会立即明白,该request
已被处理,则需要额外的同步。
在这些线程之间实现(或使用已经实现的)阻塞管道(或使用信号/事件)。我们的想法是:
-
foo
的线程执行SendRequest
-
foo
开始睡在一些select
(例如) -
RequestManager
执行请求和:- 电话
&foo::someCallback
- “唤醒”
foo
的线程(通过发送文件描述符中的某个文件foo
(使用select
))
- 电话
-
foo
是唤醒 - 检查
volatile bool
标志已经处理的请求 - 做什么它需要做
- 撤销本级标志