9.3事件内核对象学习

第八章主要涉及到了用户模式同步。

第九章进行了内核对象同步。内核对象同步应用广,缺点是性能。

内核对象包括进程、线程以及作业(Job),这些都可以用来进行同步,有未触发状态和触发状态两种,创建时,未触发状态,终止时,触发状态。但是触发后不会再回到未触发状态。布尔量分别为false和true.

windows线程同步的内核对象有:事件、可等待计时器、信号量和互斥量。

等待函数使一个线程或进程,自愿进入等待状态,直到指定的内核对象被触发。有等待单个(waitforsingleObject)和多个(waitformultiObjects)。返回结果失败有WAIT_TIMEOUT,和WAIT_FAILED,成功有WAIT_OBJECT_0,如果是等待多个,则会从WAIT_OBJECT_0和(WAIT_OBJECT_0+dwCount-1)之间的任一个值。等待多个,可能等待一个内核对象被触发,也可能等待指定的全部内核被触发。

 

这里有个等待成功所引起的副作用,即自动重置事件对象,会在触发后,事件对象又变为非触发状态。这对于waitformultipleObjects有影响,因为WaitForMultipleObjects()是原子操作,

 

事件包含引用计数、重置事件布尔量(自动重置或者手动重置),是否被触发的布尔量。

自动重置,则调度一个等待该事件的线程。手动重置,则调度所有等待该事件的线程。

通常用途:线程A初始化,然而触发另一个线程B,让线程B执行剩余的工作。

具体是线程A初始化为未触发状态,初始化完成后,则触发事件。由于线程B一直等待该事件,线程B发现事件被触发后,于是线程B变成可调度。

 

几个函数:

1,创建事件内核对象。CreateEvent()

2,设置事件为触发状态.SetEvent()

3,设置事件为未触发状态。ResetEvent()。

列了个例子。服务器端和客户端互相触发事件。

代码及注释如下:

#include "../../trunk/CmmHdr.h"
#include <Windows.h>
#include <windowsx.h>
#include <tchar.h>
#include <process.h>
#include "resource.h"

//客户端触发事件,服务器端的线程等待这个事件,以处理客户端请求
HANDLE g_heveRequestedSubmitted;
//服务器端触发事件,客户端线程等待这个事件,以处理服务器端返回的结果
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_heveRequestedSubmitted, INFINITE);
        //判断是否客户端要求服务器端关闭
        fShutdown = (NULL == g_hMainDlg) &&
            (_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));
        //让服务器线程知道客户端请求事件
        SetEvent(g_heveRequestedSubmitted);
        //等待服务器处理,返回服务器给个结果
        WaitForSingleObject(g_hevtResultReturned, INFINITE);
        //将结果放入编辑框
        Edit_SetText(GetDlgItem(hWnd, IDC_RESULT), g_szSharedRequestAndResultBuffer);

        break;
    default:
        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_heveRequestedSubmitted = CreateEvent(NULL, FALSE, FALSE, NULL);
    g_hevtResultReturned = CreateEvent(NULL, FALSE, FALSE, NULL);

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

    //客户端线程
    DialogBox(hInstanceExe, MAKEINTRESOURCE(IDD_HANDSHAKE), NULL, Dlg_Proc);
    g_hMainDlg = NULL;

    _tcscpy_s(g_szSharedRequestAndResultBuffer, _countof(g_szSharedRequestAndResultBuffer), g_szServerShutDown);
    SetEvent(g_heveRequestedSubmitted);

    //等待服务器端获取关闭线程和等待服务器端完全销毁
    HANDLE h[2];
    h[0] = g_hevtResultReturned;
    h[1] = hThreadServer;
    WaitForMultipleObjects(2, h, TRUE, INFINITE);

    CloseHandle(hThreadServer);
    CloseHandle(g_heveRequestedSubmitted);
    CloseHandle(g_hevtResultReturned);

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值