C++ 我应该选择什么样的同步方案来避免实时C++/MFC应用程序?
我想问您一个问题,关于我应该选择哪种并发工具(CMutex、CSemaphore、CEvent),以使C++/MFC应用程序成为多线程的 它是一个实时的机器视觉应用程序,现在需要并发执行,并且需要从以前的单线程状态进行重构 我的工作流程的一次迭代如下所示。我有两个生产商A、B(MFC工人),他们需要填写两个单独的数据结构(每个1个)。第三个线程,一个消费者(也是MFC工作者)被阻塞,直到两个数据从A和B都可用。然后,生产者A和B必须阻塞(每个都在其数据完成后),C必须唤醒,执行计算,取消阻塞A和B继续并再次阻塞,等待下一段C++ 我应该选择什么样的同步方案来避免实时C++/MFC应用程序?,c++,mfc,concurrency,synchronization,C++,Mfc,Concurrency,Synchronization,我想问您一个问题,关于我应该选择哪种并发工具(CMutex、CSemaphore、CEvent),以使C++/MFC应用程序成为多线程的 它是一个实时的机器视觉应用程序,现在需要并发执行,并且需要从以前的单线程状态进行重构 我的工作流程的一次迭代如下所示。我有两个生产商A、B(MFC工人),他们需要填写两个单独的数据结构(每个1个)。第三个线程,一个消费者(也是MFC工作者)被阻塞,直到两个数据从A和B都可用。然后,生产者A和B必须阻塞(每个都在其数据完成后),C必须唤醒,执行计算,取消阻塞A和
致以最诚挚的问候。我会对您的选项2做一点小小的修改-对两个事件使用CMultiLock来阻止C;然后使用另一对事件来阻止a和B。C会设置两个自动重置事件来唤醒a和B。这样,您就不再有进行重置的竞争了。C必须等待两件事情发生,因此最合理的方法是ng是指它等待两个自动重置
CEvent
对象:一个由A设置,一个由B设置
当C完成时,A和B必须各自等待通知。因为有两个线程,并且两者都必须唤醒,自然的事情是使用另一对自动重置CEvent
对象,A和B各一个。C可以在完成时同时设置这两个对象
计数为2的信号量用于唤醒C——C等待两次,A和B中的每一个通知——但这意味着C必须在第一次通知后唤醒,才能等待第二次通知,这并不理想
使用计数为2的信号量在事后唤醒a和B可能会导致被盗唤醒和混乱。C向信号量发送两次信号。a唤醒并接收信号,进行处理并通知C,然后再次等待信号量。由于B尚未唤醒,信号量仍然可用,因此a再次接收信号。同时B没有被卡住,因为它不会得到另一个信号;C被卡住,因为它将等待B的下一个值
另一种方法是使用Windows条件变量API而不是事件,但似乎没有MFC包装器。请参见我建议使用一个受互斥锁保护的计数器的信令系统。这使所有同步工作仅限于一个小类,而其他类不做任何事情
A starts
A writes A-Data
A signals
A stops
B starts
B writes B-Data
B signals
B stops
C starts
C reads A-Data and B-Data
C starts A, B
C stops
*Signal Class*
Mutex protected counter attribute
Receives signal for A, increment counter
Receives signal for B, increment counter
IF counter equals 2, clear counter and start C
您只需使用CEvent对象和WaitForMultipleObjects()即可,这允许您通过第三个参数“bWaitAll”来等待这两个对象
这是一个候选解决方案。事实上,最有可能的解决方案。尽管如此,我喜欢通过单个调用向所有(两个)排队线程发送信号的原子性。使用条件变量API将限制程序仅在Windows Vista(Server 2008)上运行或者稍后我会继续。我不会过早地进行优化;我只会首先使用第二对CEvent使其工作。然后我会计算出,从用户空间到内核空间的切换需要多少时间。相对于您的备选点。我真的需要为我使用的每个同步对象使用MFC包装器吗使用?我在MFC并发应用程序方面没有太多经验。我关心的另一件事是取消C worker,如何安全地摆脱锁定,而不使用MsgWaitForMultipleObjects中那样的可报警等待模式?你不需要所有东西都使用MFC包装器,但如果你使用MFC,那么包装器通常更容易使用我个人更喜欢C++11包装器。要在线程C等待事件时取消线程C,有几个选项。1)在可警报状态下使用
WaitForMultipleObjectsEx
或类似工具,并使用APC唤醒线程C。2)使用MsgWaitForMultipleObjects
并向C发送消息。3) 单独等待每个事件,但与第三个“取消”事件配对,因此使用“等待任何”选项先等待a+取消,然后等待B+取消。如果触发取消事件,则取消。