• 事件函数SetEvent、PulseEvent与WaitForSingleObject详解


    系统核心对象中的Event事件对象,在进程、线程间同步的时候是比较常用,发现它有两个出发函数,一个是SetEvent,还有一个PulseEvent,

    两者的区别是:

    SetEvent为设置事件对象为有信号状态;而PulseEvent也是将指定的事件设为有信号状态,

    不同的是如果是一个人工重设事件,正在等候事件的、被挂起的所有线程都会进入活动状态,函数随后将事件设回,并返回;如果是一个 自动重设事件,则正在等候事件的、被挂起的单个线程会进入活动状态,事件随后设回无信号,并且函数返回。

    也就是说在自动重置模式下PulseEvent和SetEvent的作用没有什么区别,但在手动模式下PulseEvent就有明显的不同,可以比较容易的控制程序是单步走,还是连续走。如果让循环按要求执行一次就用PulseEvent,如果想让循环连续不停的运转就用SetEvent,在要求停止的地方发个ResetEvent就OK了。

    临界区的作用:避免临界区内的数据(一般为共享的资源)被不同的线程同时访问,实现线程的同步操作。保证只能由先进入临界区的一个线程访问结束后,其他线程才可以继续访问共享的资源。
    临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用EnterCriticalSection()和LeaveCriticalSection()函数去标识和释放一个临界区。所用到的CRITICAL_SECTION结构对象必须经过InitializeCriticalSection()的初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码都处在此临界区的保护之下。否则临界区将不会起到应有的作用,共享资源依然有被破坏的可能。
     

    以下为临界区的使用方法:

    *.h头文件:

    #include <winbase.h>

    CRITICAL_SECTION  m_cs_test; ///< 定义一个临界区对象

    *.cpp源文件使用方法:

    在类的构造函数内初始化临界区对象

    //该函数必须在任何线程调用EnterCriticalSection函数之前被调用,否则结果将是很难预计的

    ::InitializeCriticalSection(&m_cs_test);

    在类的虚构函数内释放临界区对象

    ::DeleteCriticalSection(&m_cs_test); 

    使用方法一:

    在所需要使用的函数中开始锁定:

    CCriticalSectionLock lock(m_cs_test);

    在函数生命期结束后会自动解锁。 

    使用方法二:

    //进入开始锁定数据:保护共享资源只被一个线程调用

    EnterCriticalSection(&m_cs_test);

    ...//do something you want to

    //离开锁定的数据:允许共享资源被其他的线程调用

    LeaveCriticalSection(&m_cs_test);

    注意:

    在使用临界区时,一般不允许其运行时间过长,只要进入临界区的线程还没有离开,其他所有试图进入此临界区的线程都会被挂起而进入到等待状态,并会在一定程度上影响程序的运行性能。尤其需要注意的是不要将等待用户输入或是其他一些外界干预的操作包含到临界区。如果进入了临界区却一直没有释放,同样也会引起其他线程的长时间等待。换句话说,在执行了EnterCriticalSection()语句进入临界区后无论发生什么,必须确保与之匹配的LeaveCriticalSection()都能够被执行到。可以通过添加结构化异常处理代码来确保LeaveCriticalSection()语句的执行。虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。

    WaitForSingleObject函数:

    DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);

    参数:
    hHandle:指定对象或事件的句柄;
    dwMilliseconds: 等待时间,以毫妙为单位,当超过等待时间时,此函数将返回。如果该参数设置为0,则该函数立即返回,如果设置为INFINITE,则该函数直到有信号才返回。
    返回值:
    如果此函数成功,该函数的返回之标识了引起该函数返回的事件。返回值如下:
       WAIT_ABANDONED(0x00000080L)
       指定的对象是一个互斥对象,该对象没有被拥有该对象的线程在线程结束前释放。互斥对象的所有权被同意授予调用该函数的线程。互斥对象被设置成为无信号状态。
       WAIT_OBJECT_0 (0x00000000L)
       指定的对象出有有信号状态。
       WAIT_TIMEOUT (0x00000102L)
       超过等待时间,指定的对象处于无信号状态
    如果失败,返回 WAIT_FAILED;

    在程序中,对每个线程时间做了控制!

    HANDLE hThread1;

    hThread1=CreateThread(NULL,0,DataHandle,(LPVOID)&d,0,NULL);   //创建线程处理数据

    if(WaitForSingleObject(hThread1,     

      1000     //时限   

      )!= WAIT_OBJECT_0)   

    {   

      WriteLog(logFile,"终止线程");

      TerminateThread(hThread1,0);  

             }

  • 相关阅读:
    python中RabbitMQ的使用(远程过程调用RPC)
    python中RabbitMQ的使用(交换机,广播形式)
    python中RabbitMQ的使用(路由键模糊匹配)
    python中sys.argv[]的使用
    python中RabbitMQ的使用(路由键)
    操作远程RabbitMQ
    python中RabbitMQ的使用(工作队列)
    python中RabbitMQ的使用(安装和简单教程)
    python中eval()和json.dumps的使用
    python使用MySQLdb模块连接MySQL
  • 原文地址:https://www.cnblogs.com/zsq1993/p/6005936.html
Copyright © 2020-2023  润新知