Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我应该选择什么样的同步方案来避免实时C++/MFC应用程序?_C++_Mfc_Concurrency_Synchronization - Fatal编程技术网

C++ 我应该选择什么样的同步方案来避免实时C++/MFC应用程序?

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和

我想问您一个问题,关于我应该选择哪种并发工具(CMutex、CSemaphore、CEvent),以使C++/MFC应用程序成为多线程的

它是一个实时的机器视觉应用程序,现在需要并发执行,并且需要从以前的单线程状态进行重构

我的工作流程的一次迭代如下所示。我有两个生产商A、B(MFC工人),他们需要填写两个单独的数据结构(每个1个)。第三个线程,一个消费者(也是MFC工作者)被阻塞,直到两个数据从A和B都可用。然后,生产者A和B必须阻塞(每个都在其数据完成后),C必须唤醒,执行计算,取消阻塞A和B继续并再次阻塞,等待下一段

  • 我不能使用队列(类似于演员)——阻塞是一项要求 :(
  • 我尝试了CEvent,它成功了。自动重置A、B的事件以解除A的阻止 C上的CMultiLock调用,然后从C到 解锁A和B等待后一个事件。我关心的是何时 重置此事件(例如,如果未完成整个设置,然后重置。)
  • 多个2的信号量代表更好的解决方案吗

  • 致以最诚挚的问候。

    我会对您的选项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+取消。如果触发取消事件,则取消。