您的位置:

深入解析waitforsingleobject

一、waitforsingleobject时间

waitforsingleobject是Windows API中一种同步机制,其作用是等待一个关键对象的信号,或者等待某个时间间隔,以等待被通知、满足条件或者时间到达等情况发生。在使用waitforsingleobject时,可以通过参数timeout来设置等待的时间。如果在timeout时间内对象被释放,则该函数会返回WAIT_OBJECT_0,如果timeout时间内对象仍未被释放,则返回WAIT_TIMEOUT。

waitforsingleobject函数有一个非常棒的特性,它可以将调用的线程挂起,直到对象变成可以用。如果将timeout值设为0,那么 waitforsingleobject将会对对象的状态进行查询,如果处于可用状态,该函数会立即返回;否则,该函数会将线程挂起到对象变为可用。

DWORD WaitForSingleObject(
  HANDLE hHandle, // 要等待的对象的句柄
  DWORD  dwMilliseconds // 等待的时间,以毫秒为单位。设置为INFINITE表示等待无限长的时间。
);

二、waitforsingleobject返回1

waitforsingleobject函数返回值1代表WAIT_FAILED,这意味着这次等待没有成功。其中一种可能的情况是传入了一个无效的句柄。此外,WAIT_FAILED可能是因为内部错误导致的,这种情况可能需要进一步的调查和排除。

为了帮助你提高代码的鲁棒性,可以将参数hHandle传入WAIT_OBJECT_0_INTERNAL,这样函数将会返回0,代表成功等待,或者返回WAIT_TIMEOUT。

#define WAIT_OBJECT_0_INTERNAL ((DWORD)0x00000001L)

HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
DWORD dwWaitResult = WaitForSingleObject(hEvent, INFINITE);
if (dwWaitResult == WAIT_FAILED) {
  // handle wait failed.
}

三、waitforsingleobject和sleep

waitforsingleobject和sleep都是Windows API中的同步机制,它们都可以用来等待一些事件的发生。但是,waitforsingleobject有一个非常明显的优点:它可以接收Windows内核对象的句柄作为参数。因此,在处理文件、进程、线程等资源时,waitforsingleobject至关重要。

相比之下,sleep函数一般用于“暂停”程序的执行,仅当你希望暂时停止程序时才应该使用。但是,如果需要等待某个资源释放,sleep函数则是不适宜的。

由于waitforsingleobject可以接收的对象较多,因此waitforsingleobject可以用于任何需要等待对象的应用程序中。

HANDLE hFile = CreateFile("test.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
  WaitForSingleObject(hFile, INFINITE);
  //...
  CloseHandle(hFile);
}
else {
  // handle file creation failed.
}

四、waitforsingleobject的作用qt

在Qt中,waitforsingleobject可以用来等待信号的触发。QEventLoop借助waitforsingleobject等待任意时间间隔,直到接收到一个触发某个事件的信号。

void MyObject::someLongRunningFunction() {
  //...
  QEventLoop waitLoop;
  connect(this, &MyObject::someSignal, &waitLoop, &QEventLoop::quit);
  connect(this, &MyObject::someTimeoutSignal, &waitLoop, &QEventLoop::quit);
  QTimer::singleShot(5000, this, &MyObject::someTimeoutSignal);
  waitLoop.exec();
  //...
}

五、waitforsingleobject在switch中

在一些特定的编程场景中,很常见的一种操作是使用switch语句来处理不同的Windows消息。此时,waitforsingleobject函数可以用来等待UserModeConsoleInput事件或用户输入事件等。

借助waitforsingleobject来等待这些事件,可以减轻程序的负担,同时还能简化程序的结构。

DWORD ConsoleInputLoop() {
  while (true) {
    DWORD dwWaitResult = WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), INFINITE);
        
    if (dwWaitResult == WAIT_OBJECT_0) {
      //process console input
          
      INPUT_RECORD irInBuf[128];
      DWORD dwNumRead;
      if (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), irInBuf, 128, &dwNumRead)) {
        //...
      }
      else {
        break;
      }
    }
    
    // handle wait result
    switch (dwWaitResult) {
      case WAIT_OBJECT_0 + 1:
        //...
        break;
      case WAIT_OBJECT_0 + 2:
        //...
        break;
      case WAIT_OBJECT_0 + 3:
        //...
        break;
      default:
        break;
    }
  }
}

六、waitforsingleobject卡顿

正常情况下,waitforsingleobject应该是一个非常高效的API。但是,在某些情况下,waitforsingleobject会出现阻塞、死锁等问题。这种情况下通常是因为等待的对象没有被正确释放或其状态不正确而导致的。

为了避免waitforsingleobject的卡顿,可以尝试使用WaitForMultipleObjects,减少waitforsingleobject的调用次数,并确保在使用waitforsingleobject时对象的状态都是正确的。

HANDLE hEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE hEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE hEvents[2] = {hEvent1, hEvent2};
WaitForMultipleObjects(2, hEvents, TRUE, INFINITE);
//...

结语

waitforsingleobject是Windows API中重要的同步机制之一,它可以用来等待关键对象的信号、资源的释放或其他指定的事件。waitforsingleobject的使用不仅可以提高程序的效率,还可以简化程序的结构和设计。