内核对象和线程同步—WaitForSingleObject

WaitForSingleObject

       当进程正在运行的时候,进程内核对象处于未通知状态,当进程终止运行的时候,它就变 为已通知状态。进程内核对象中是个布尔值,当对象创建时,该值被初始化为FALSE(未通知 状态)。当进程终止运行时,操作系统自动将对应的对象布尔值改为TRUE,表示该对象已经得 到通知。

       等待函数可使线程自愿进入等待状态,直到一个特定的内核对象变为已通知状态为止。
       DWORD  WaitForSingleObject (HANDLE hObject, DWORD dwMilliseconds);

       当线程调用该函数时,第一个参数hObject标识一个能够支持被通知/未通知的内核对象 (前面列出的任何一种对象都适用)。第二个参数dwMilliseconds允许该线程指明,为了等待该 对象变为已通知状态,它将等待多长时间。 调用下面这个函数将告诉系统,调用函数准备等待到hProcess句柄标识的进程终止运行为止:
WaitForSingleObject( hProcess, INFINITE );

       第二个参数告诉系统,调用线程愿意永远等待下去(无限时间量),直到该进程终止运行。 通常情况下,INFINITE是作为第二个参数传递给WaitForSingeObject   也可以传递 任何一个值(以毫秒计算)。顺便说一下, INFINITE已经定义为0xFFFFFFFF(或-1)。当然, 传递INFINITE有些危险。如果对象永远不变为已通知状态,那么调用线程永远不会被唤醒, 它将永远处于死锁状态,不过,它不会浪费宝贵的CPU时间。

     WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回; 若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。
WAIT_ABANDONED 0x00000080:当hHandle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值。
WAIT_OBJECT_0 0x00000000 :指定的对象出有有信号状态
WAIT_TIMEOUT 0x00000102:等待超时
WAIT_FAILED 0xFFFFFFFF :出现错误,可通过GetLastError得到错误代码

#include "..\CommonFiles\CmnHdr.h"     /* See Appendix A. */
#include <windowsx.h>
#include <tchar.h>
#include "Resource.h"


///

// 提交事件对象
HANDLE g_hevtRequestSubmitted;

// 返回事件对象
HANDLE g_hevtResultReturned;

// 共享缓存区
TCHAR  g_szSharedRequestAndResultBuffer[1024];

// 特殊字符内容
TCHAR  g_szServerShutdown[] = TEXT("Server Shutdown");

// 全局窗口句柄
HWND   g_hMainDlg;

///
DWORD WINAPI ServerThread(PVOID pvParam) {

   // 循环等待标志位
   BOOL fShutdown = FALSE;

   while (!fShutdown) {

      // 等待提交事件对象为通知状态
      WaitForSingleObject(g_hevtRequestSubmitted, INFINITE);

      // 判断窗口是否关闭和是否提交了特殊字符,有则准备停止服务线程
      fShutdown = 
         (g_hMainDlg == NULL) &&
         (_tcscmp(g_szSharedRequestAndResultBuffer, g_szServerShutdown) == 0);

      if (!fShutdown) {
         // 反转共享缓存区数据内容
         _tcsrev(g_szSharedRequestAndResultBuffer);
      }

      // 服务线程处理好,将返回事件设置通知状态
      SetEvent(g_hevtResultReturned);
   }

   return(0);
}

///
// 初始化
BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) {

   chSETDLGICONS(hwnd, IDI_HANDSHAKE);

   Edit_SetText(GetDlgItem(hwnd, IDC_REQUEST), TEXT("Some test data"));

   g_hMainDlg = hwnd;

   return(TRUE);
}

///
// 窗体事件处理
void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) {

   switch (id) {

      case IDCANCEL:
         EndDialog(hwnd, id);
         break;

      case IDC_SUBMIT:  // 提交事件
      
         // 获取输入的数据,保存到共享缓存区
         Edit_GetText(GetDlgItem(hwnd, IDC_REQUEST), 
            g_szSharedRequestAndResultBuffer, 
            _countof(g_szSharedRequestAndResultBuffer));

         // 将提交的事件对象设置为通知状态等待返回的事件对象
         SignalObjectAndWait(g_hevtRequestSubmitted, g_hevtResultReturned, INFINITE, false);

         // 服务线程处理好,显示到界面
         Edit_SetText(GetDlgItem(hwnd, IDC_RESULT), 
            g_szSharedRequestAndResultBuffer);

         break;
   }
}

///
// 消息回调函数
INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
   
   switch (uMsg) {
      chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
      chHANDLE_DLGMSG(hwnd, WM_COMMAND,    Dlg_OnCommand);
   }

   return(FALSE);
}

///
// 主线程
int WINAPI _tWinMain(HINSTANCE hInstanceExe, HINSTANCE, PTSTR, int) {

   // 创建2个未通知的自动重置事件对象
   g_hevtRequestSubmitted = CreateEvent(NULL, FALSE, FALSE, NULL);
   g_hevtResultReturned   = CreateEvent(NULL, FALSE, FALSE, NULL);

   // 启动服务线程
   DWORD dwThreadID;
   HANDLE hThreadServer = chBEGINTHREADEX(NULL, 0, ServerThread, NULL, 
      0, &dwThreadID);

   // 进入Dlg_Proc回调函数,当窗口关闭退出DialogBox
   DialogBox(hInstanceExe, MAKEINTRESOURCE(IDD_HANDSHAKE), NULL, Dlg_Proc);
   
   g_hMainDlg = NULL;

   // 拷贝特殊的字符进入共享缓存区
   _tcscpy_s(g_szSharedRequestAndResultBuffer, 
      _countof(g_szSharedRequestAndResultBuffer), g_szServerShutdown);
   // 将提交事件设置通知状态,服务线程被唤醒
   SetEvent(g_hevtRequestSubmitted);

   // 等待服务线程设置的事件状态和线程状态
   HANDLE h[2];
   h[0] = g_hevtResultReturned;
   h[1] = hThreadServer;
   WaitForMultipleObjects(2, h, TRUE, INFINITE);
   
   // 服务线程退出则退出等待,开始销毁内核对象
   CloseHandle(hThreadServer);      
   CloseHandle(g_hevtRequestSubmitted);      
   CloseHandle(g_hevtResultReturned);      

   return(0);
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值