【发布时间】:2013-04-02 06:11:20
【问题描述】:
我的代码调用了来自 3rd 方库的函数。我们称这个函数为SomeFunc
void SomeFunc(void (*callBack) (int));
如您所见,SomeFunc 采用回调函数参数。一旦 SomeFunc 被调用,调用线程将继续进行,并且库将在不同的线程上多次执行回调——传递不同的状态代码。
我的要求是调用 SomeFunc 的线程(又名主线程)应该等到某些状态代码被传递给回调。到目前为止,我有这样的东西
CEvent *pEvt = NULL;
void myCallBack(int code) {
if(code == SOME_MAGIC_NUM) pEvt->SetEvent(); // signal thread waiting for this event obj they can continue
}
int main (int argc, char** argv) {
pEvt = new CEvent(FALSE, TRUE);
SomeFunc(myCallBack); // This doesn't block, main thread will progress to next line
WaitForSingleObject(pEvt, 5000); // wait here until 3rd party library call myCallBack with code SOME_MAGIC_NUM -- or if it doesn't after 5 seconds, continue
// do interesting stuff here..
return EXIT_SUCCESS;
}
如果我只在上面的主线程/主函数上执行此操作,这似乎很好。但是,如果多个线程可以执行上面 main 中的代码块,我的问题是它们将共享对全局 pEvt 变量的引用,它会搞砸
我应该在这里采用的最佳代码设计方法是什么?理想情况下,我想更改回调函数签名以接受对 CEvent 对象的引用,但由于它是第 3 方库,我无法这样做。
【问题讨论】:
-
目前还不清楚:
SomeFunc()是否产生了您的辅助线程,然后返回给它的调用者(在本例中为main())?我之所以问,是因为您在多线程上下文中提出了这个问题,然后继续显示完全没有多线程的代码。 -
正确,SomeFunc() 产生了辅助线程——我们称之为“线程 X”。从 Thread X 它将调用 myCallBack 并传递不同的代码参数。主线程和线程 X 将同时执行,这就是为什么我在上面使用
WaitForSingleObject(pEvt, 5000)来暂停主线程,直到我乐于进行 -
请问为什么需要多个线程来监控单个回调事件?
-
无论如何,你在后续代码中引入了竞争条件。正如所写,不能保证
main()不会在实现 SomeFunc() 的库管理的线程完成之前完成。此外,5000是因为……? 4999 还不够,5001 太多了?您描述代码中等待的评论不准确。它应该是:“在这里等到第 3 方库调用 myCallBack,代码为 SOME_MAGIC_NUM,或者我只是在大约 5 秒后不在乎。”但我假设你确实在乎. -
@jwalk,代码是 Web 服务实现的一部分。每次客户端发出请求时,都会在单独的工作线程上提供响应,但恐怕全局变量 pEvt 会在所有工作线程上共享。如果 2 个客户端同时调用 Web 服务,就会出现并发问题。我考虑过将类成员作为回调传递,但 C++ 有不同的函数指针类型,它不会编译。
标签: c++ multithreading winapi concurrency