增加WaitforMultipleObjects的MAXIMUM_WAIT_OBJECTS

时间:2011-02-27 23:19:12

标签: c++ multithreading winapi

等待MAXIMUM_WAIT_OBJECTS以外的更多对象的最简单方法是什么? MSDN列出了这个:

  • 创建一个线程以等待MAXIMUM_WAIT_OBJECTS句柄,然后等待该线程加上其他句柄。使用此技术将句柄分成MAXIMUM_WAIT_OBJECTS
  • 致电RegisterWaitForSingleObject等待每个手柄。来自线程池的等待线程等待MAXIMUM_WAIT_OBJECTS个已注册的对象,并在发出对象信号或超时间隔到期后分配工作线程。

但他们都不是很清楚。这种情况将等待一大堆超过一千个线程处理。

3 个答案:

答案 0 :(得分:6)

如果您发现自己在等待大量对象,则可能需要查看IO完成端口。对于大量并行操作,IOCP效率更高。

IOCP的名称具有误导性,您也可以轻松地将IOCP用于您自己的同步结构。

答案 1 :(得分:3)

我自己在WaitForMultipleObjects中遇到了这个限制,并得出结论我有三个选择:

  • 选项1.将代码更改为以小于MAXIMUM_WAIT_OBJECTS的批量创建单独的线程以调用WaitForMultipleObjects 。我决定反对这个选项,因为如果已有64个以上的线程争夺相同的资源,我想尽可能避免创建更多的线程。
  • 选项2. 使用不同的技术重新实现代码(例如,IOCP)。我也决定反对这一点,因为我正在研究的代码库已经过试用,测试和稳定。另外,我有更好的事情要做!
  • 选项3.实现一个函数,将对象拆分为小于MAXIMUM_WAIT_OBJECTS的批次,在同一个线程中重复调用WaitForMultipleObjects

所以,选择了选项3 - 这是我最终实现的代码......

class CtntThread
{
    public: 
        static DWORD WaitForMultipleObjects( DWORD, const HANDLE*, DWORD millisecs );
};

DWORD CtntThread::WaitForMultipleObjects( DWORD count, const HANDLE *pHandles, DWORD millisecs )
{
    DWORD retval = WAIT_TIMEOUT;

    // Check if objects need to be split up. In theory, the maximum is
    // MAXIMUM_WAIT_OBJECTS, but I found this code performs slightly faster
    // if the object are broken down in batches smaller than this.
    if ( count > 25 )
    {
        // loop continuously if infinite timeout specified
        do
        {
            // divide the batch of handles in two halves ...
            DWORD split = count / 2;
            DWORD wait = ( millisecs == INFINITE ? 2000 : millisecs ) / 2;
            int random = rand( );

            // ... and recurse down both branches in pseudo random order
            for ( short branch = 0; branch < 2 && retval == WAIT_TIMEOUT; branch++ )
            {
                if ( random%2 == branch ) 
                {
                    // recurse the lower half
                    retval = CtntThread::WaitForMultipleObjects( split, pHandles, wait );
                }
                else
                {
                    // recurse the upper half
                    retval = CtntThread::WaitForMultipleObjects( count-split, pHandles+split, wait );
                    if ( retval >= WAIT_OBJECT_0 && retval < WAIT_OBJECT_0+split ) retval += split;
                }
            }
        }
        while ( millisecs == INFINITE && retval == WAIT_TIMEOUT );
    }
    else
    {
        // call the native win32 interface
        retval = ::WaitForMultipleObjects( count, pHandles, FALSE, millisecs );
    }

    // done
    return ( retval );
}

答案 2 :(得分:2)

看看here

  

如果你需要等待超过MAXIMUM_WAIT_OBJECTS句柄,你可以创建一个单独的线程来等待MAXIMUM_WAIT_OBJECTS,然后等待这些线程完成。使用此方法,您可以创建MAXIMUM_WAIT_OBJECTS个线程,每个线程都可以等待MAXIMUM_WAIT_OBJECTS对象句柄。