WaitForMultipleObjects多相机同时触发拍摄有时候卡死处理

最近在做关于多相机同时触发拍摄的项目,需要做到多线程等待同步的功能,但是单独的使用有时候会出现接收不到信号的问题,偶然看到了这篇文章,写的还不错,然后分析了自己的问题,发现了问题所在,分享给大家,可以帮到大家

举个例子:我们需要在一个线程中处理从完成端口、数据库、和可等待定时器来的数据。

WaeeitForMultipleObjects是Windows中的一个功能非常强大的函数,几乎可以等待Windows中的所有的内核对象(关于该函数的描述和例子见MSDN,)。

1,函数原型与概述

原型:DWORD WaitForMultipleObjects(

DWORD nCount,

const HANDLE* lpHandles,

BOOL bWaitAll,

DWORD dwMilliseconds

);

2,参数

Parameters

nCount

[in] lpHandles指向的数组中的对象句柄数。对象句柄的最大数量为MAXIMUM_WAIT_OBJECTS。此参数不能为零。

lpHandles

[in]一组对象句柄。该数组可以包含不同类型对象的句柄。它可能不包含同一句柄的多个副本。

如果其中一个句柄在等待仍处于暂挂状态时关闭,则该函数的行为未定义。

句柄必须具有SYNCHRONIZE访问权限。

Windows NT/2000/XP: 句柄必须具有同步访问权限。

Windows 95/98/Me:任何句柄都可以是用DuplicateHandle创建的另一个句柄的副本。

bWaitAll

[in] 如果此参数为TRUE,则在lpHandles数组中的所有对象的状态发出信号时,该函数返回。如果为FALSE,则当任何一个对象的状态设置为信号时,该函数返回。在后一种情况下,返回值表示其状态导致函数返回的对象。

dwMilliseconds

[in] 超时间隔,以毫秒为单位。如果指定了非零值,则该函数将一直等到指定的对象发出信号或经过间隔。如果dwMilliseconds为零,则如果未发出指示对象,则该函数不会进入等待状态;它总是立即返回。如果dwMillisecondsINFINITE,则仅在发出指定对象信号时才返回该函数。

3,返回值

如果函数成功,返回值表示该事件导致该函数返回。这个值可以是下列之一。

 

WAIT_OBJECT_0到(WAIT_OBJECT_0 + nCount - 1如果bWaitAll为TRUE),则返回值表明所有指定对象的状态信号。

如果bWaitAll为FALSE,则返回值减去不是WAIT_OBJECT_0表示lpHandles数组的对象的满意指数的等待。如果多个对象在通话过程中信号成为,这是与所有的信号对象的最小索引值的信号对象的数组索引。

WAIT_ABANDONED_0至(WAIT_ABANDONED_0 + nCount - 1)如果bWaitAll为TRUE,则返回值表明所有指定对象的状态是触发的,并且至少对象之一,是一个废弃的互斥对象。

If bWaitAll is FALSE, the return value minus WAIT_ABANDONED_0 indicates the lpHandles array index of an abandoned mutex object that satisfied the wait

如果bWaitAll为FALSE,则返回值减去WAIT_ABANDONED_0 表示一个废弃的互斥对象在lpHandles数组中的下标,满足等待。

WAIT_TIMEOUTThe超时间隔已过,由bWaitAll参数指定的条件得不到满足。

 

当WaitForMultipleObjects等到多个内核对象的时候,如果它的bWaitAll 参数设置为false。其返回值减去WAIT_OBJECT_0 就是参数lpHandles数组的序号。如果同时有多个内核对象被触发,这个函数返回的只是其中序号最小的那个。如果为TRUE 则等待所有信号量有效再往下执行。(FALSE 当有其中一个信号量有效时就向下执行)

问题就在这里,我们如何可以获取所有被同时触发的内核对象。一个典型的实现方法就是:用WaitForMultipleObjects等待所有的这些事件。如果完成端口,数据库发过来的数据量非常大,可等待定时器时间也只有几十毫秒。那么这些事件同时触发的几率可以说非常大,我们不希望丢弃任何一个被触发的事件。那么如何能高效地实现这一处理呢?

 

多个内核对象被触发时,WaitForMultipleObjects选择其中序号最小的返回。而WaitForMultipleObjects它只会改变使它返回的那个内核对象的状态。

这儿又会产生一个问题,如果序号最小的那个对象频繁被触发,那么序号比它大的内核对象将得不到被处理的机会。

为了解决这一问题,可以采用双WaitForMultipleObjects检测机制来实现。见下面的例子:

 

DWORD WINAPI ThreadProc(LPVOID lpParameter)   
{   
       DWORD dwRet = 0;   
       int nIndex = 0;   
      while(1)   
      {   
           dwRet = WaitForMultipleObjects(nCount,pHandles,false,INFINITE);   
           switch(dwRet)   
           {   
            case WAIT_TIMEOUT:   break;   
            case WAIT_FAILED:   return 1;   
            default:   
            {   
               nIndex = dwRet - WAIT_OBJECT_0;   
               ProcessHanlde(nIndex++);   //同时检测其他的事件   
               while(nIndex < nCount) //nCount事件对象总数   
               {  
                  dwRet = WaitForMultipleObjects(nCount - nIndex,&pHandles[nIndex],false,0);   
                  switch(dwRet)   
                  {   
                   case WAIT_TIMEOUT:   
                   nIndex = nCount; //退出检测,因为没有被触发的对象了.   
                   break;   
                   case WAIT_FAILED:   
                   return 1;   
                   default:   
                   {   
                    nIndex = nIndex + dwRet - WAIT_OBJECT_0;   
                    ProcessHanlde(nIndex++);   
                   }   
                    break ;  
                  }   
              }//end-while   
            }   
            break;   
           }   
       }   
       return 0;   
}

你可能感兴趣的:(IT)