zoukankan      html  css  js  c++  java
  • 使用事件对象

    事件对象:也属于内核对象(mutex属于内核对象),包含以下三个成员
       1> 使用计数
       2> 用于指明该事件是一个自动重置的事件还是一个人工重置的是件的bool值
       3> 用于指明该事件处于已通知状态还是未通知状态的bool值

    使用CreateEvent函数创建事件对象(用一个HANDLE记录)

    使用WaitForSingleObject()/WaitForMultipleObject()函数来等待事件对象变为有信号状态。

    使用SetEvent()将事件对象置为有信号状态,使用ResetEvent()将事件对象置为无信号状态

     

    注释1:对于人工重置的事件对象,需要手动SetEvent和ResetEvent

    注释2:对于自动重置的事件对象,需要手动SetEvent为有信号状态,每次有一个Wait等到它的Thread时,它会自动重置为无信号状态

    #include <windows.h>
    #include
    <stdio.h>

    #define THREADCOUNT 4

    ///事件对象,一个全局写EventObj,4个读EventObj
    HANDLE ghGlobalWriteEvent;
    HANDLE ghReadEvents[THREADCOUNT];

    ///线程响应函数
    DWORD WINAPI ThreadProc(LPVOID);

    void CreateEventsAndThreads(void)
    {
    HANDLE hThread;
    DWORD i, dwThreadID;

    ///创建人工重置、命名的事件对象,初始状态为有信号
    ///此事件对象用于给主线程来阻止4个读线程的读操作
    ghGlobalWriteEvent = CreateEvent(
    NULL,
    // default security attributes
    TRUE, // manual-reset event
    TRUE, // initial state is signaled
    TEXT("WriteEvent") // object name
    );

    if (ghGlobalWriteEvent == NULL)
    {
    printf(
    "CreateEvent failed (%d)\n", GetLastError());
    return;
    }
    ///保证应用程序只有一个实例运行:通过创建一个命名的事件对象
    else if ( GetLastError() == ERROR_ALREADY_EXISTS )
    {
    printf(
    "Named event already exists.\n");
    return;
    }

    // Create multiple threads and an auto-reset event object
    // for each thread. Each thread sets its event object to
    // signaled when it is not reading from the shared buffer.

    for(i = 0; i < THREADCOUNT; i++)
    {
    // Create the auto-reset event
    ///创建自动重置、匿名的事件对象,初始状态为有信号
    ghReadEvents[i] = CreateEvent(
    NULL,
    // no security attributes
    FALSE, // auto-reset event
    TRUE, // initial state is signaled
    NULL); // object not named

    if (ghReadEvents[i] == NULL)
    {
    printf(
    "CreateEvent failed (%d)\n", GetLastError());
    return;
    }

    ///创建Thread,传入各自对应的EventHandle
    hThread = CreateThread(NULL,
    0,
    ThreadProc,
    &ghReadEvents[i], // pass event handle
    0,
    &dwThreadID);

    if (hThread == NULL)
    {
    printf(
    "CreateThread failed (%d)\n", GetLastError());
    return;
    }
    }
    }

    void WriteToBuffer(VOID)
    {
    DWORD dwWaitResult, i;

    ///将ghGlobalWriteEvent重置为无信号状态,用来阻止4个读线程的读操作
    if (! ResetEvent(ghGlobalWriteEvent) )
    {
    printf(
    "ResetEvent failed (%d)\n", GetLastError());
    return;
    }

    ///等待所有的读线程完成read,即ghReadEvents皆变为有信号状态
    dwWaitResult = WaitForMultipleObjects(
    THREADCOUNT,
    // number of handles in array
    ghReadEvents, // array of read-event handles
    TRUE, // wait until all are signaled
    INFINITE); // indefinite wait,无限等待

    switch (dwWaitResult)
    {
    ///所有的read-event对象皆变为有信号状态
    case WAIT_OBJECT_0:
    // TODO: Write to the shared buffer
    printf("Main thread writing to the shared buffer...\n");
    break;

    // An error occurred
    default:
    printf(
    "Wait error: %d\n", GetLastError());
    ExitProcess(
    0);
    }

    ///将ghGlobalWriteEvent事件对象重置为有信号状态
    if (! SetEvent(ghGlobalWriteEvent) )
    {
    printf(
    "SetEvent failed (%d)\n", GetLastError());
    ExitProcess(
    0);
    }

    ///将ghReadEvents事件对象皆重置为有信号状态
    for(i = 0; i < THREADCOUNT; i++)
    if (! SetEvent(ghReadEvents[i]) )
    {
    printf(
    "SetEvent failed (%d)\n", GetLastError());
    return;
    }
    }

    void CloseEvents()
    {
    int i;

    for( i=0; i < THREADCOUNT; i++ )
    CloseHandle(ghReadEvents[i]);

    CloseHandle(ghGlobalWriteEvent);
    }

    void main()
    {
    int i;

    // TODO: Create the shared buffer

    // Create the events and THREADCOUNT threads to read from the buffer

    CreateEventsAndThreads();

    // Write to the buffer three times, just for test purposes

    for(i=0; i < 3; i++)
    WriteToBuffer();

    // Close the events

    CloseEvents();
    }

    DWORD WINAPI ThreadProc(LPVOID lpParam)
    {
    DWORD dwWaitResult;
    HANDLE hEvents[
    2];

    hEvents[
    0] = *(HANDLE*)lpParam; // thread's read event
    hEvents[1] = ghGlobalWriteEvent; // global write event

    ///等待hEvents[0]和hEvents[1]变为有信号状态,也就是ghReadEvents[i]和ghGlobalWriteEvent
    dwWaitResult = WaitForMultipleObjects(
    2, // number of handles in array
    hEvents, // array of event handles
    TRUE, // wait till all are signaled,当所有信号量都变为有信号状态,函数才返回
    INFINITE); // indefinite wait,无限等待

    switch (dwWaitResult)
    {
    // 所有的EventHandle都变为有信号状态
    case WAIT_OBJECT_0:
    // TODO: Read from the shared buffer
    printf("Thread %d reading from buffer...\n",
    GetCurrentThreadId());
    break;

    // An error occurred
    default:
    printf(
    "Wait error: %d\n", GetLastError());
    ExitThread(
    0);
    }

    //重置ghReadEvents[i]为有信号状态,见注释2
    if (! SetEvent(hEvents[0]) )
    {
    printf(
    "SetEvent failed (%d)\n", GetLastError());
    ExitThread(
    0);
    }

    return 1;
    }

  • 相关阅读:
    base64编码
    URL编码和解码
    Android MineType
    Gzip压缩
    关于文件与文件系统的压缩与打包命令-Linux(笔记)
    tesseract的编译安装
    HDOJ How many ways?? 2157【矩阵高速幂】
    [ACM] POJ 3253 Fence Repair (Huffman树思想,优先队列)
    6.非关系型数据库(Nosql)之mongodb:集群(主从复制)
    androidproject有红色叹号的解决方式
  • 原文地址:https://www.cnblogs.com/sifenkesi/p/1983837.html
Copyright © 2011-2022 走看看