VC++线程同步解析
2012-08-10 14:21:29 来源:WEB开发网核心提示:WaitForMultipleObjects()与WaitForSingleObject()类似,同时监视位于句柄数组中的所有句柄,VC++线程同步解析(4),这些被监视对象的句柄享有平等的优先权,任何一个句柄都不可能比其他句柄具有更高的优先权,而构造函数则履行了原CreateEvent()函数创建事件对象的职责,其函
WaitForMultipleObjects()与WaitForSingleObject()类似,同时监视位于句柄数组中的所有句柄。这些被监视对象的句柄享有平等的优先权,任何一个句柄都不可能比其他句柄具有更高的优先权。WaitForMultipleObjects()的函数原型为:
DWORD WaitForMultipleObjects(
DWORD nCount, // 等待句柄数
CONST HANDLE *lpHandles, // 句柄数组首地址
BOOL fWaitAll, // 等待标志
DWORD dwMilliseconds // 等待时间间隔
);
参数nCount 指定了要等待的内核对象的数目,存放这些内核对象的数组由lpHandles 来
指向。fWaitAll 对指定的这nCount 个内核对象的两种等待方式进行了指定,为TRUE 时当所
有对象都被通知时函数才会返回,为FALSE 则只要其中任何一个得到通知就可以返回。
dwMilliseconds 在这里的作用与在WaitForSingleObject()中的作用是完全一致的。如果
等待超时,函数将返回WAIT_TIMEOUT。如果返回WAIT_OBJECT_0 到
WAIT_OBJECT_0+nCount-1 中的某个值,则说明所有指定对象的状态均为已通知状态(当
fWaitAll 为TRUE 时)或是用以减去WAIT_OBJECT_0 而得到发生通知的对象的索引(当
fWaitAll 为FALSE 时)。如果返回值在WAIT_ABANDONED_0 与
WAIT_ABANDONED_0+nCount-1 之间,则表示所有指定对象的状态均为已通知,且其中至
少有一个对象是被丢弃的互斥对象(当fWaitAll 为TRUE 时),或是用以减去WAIT_OBJECT_0
表示一个等待正常结束的互斥对象的索引(当fWaitAll 为FALSE 时)。 下面给出的代码主要
展示了对WaitForMultipleObjects()函数的使用。通过对两个事件内核对象的等待来控制线
程任务的执行与中途退出:
// 存放事件句柄的数组
HANDLE hEvents[2];
UINT ThreadProc14(LPVOID pParam)
{
// 等待开启事件
DWORD dwRet1 = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
// 如果开启事件到达则线程开始执行任务
if (dwRet1 == WAIT_OBJECT_0)
{
AfxMessageBox("线程开始工作!");
while (true)
{
for (int i = 0; i < 10000; i++);
// 在任务处理过程中等待结束事件
DWORD dwRet2 = WaitForMultipleObjects(2, hEvents, FALSE, 0);
// 如果结束事件置位则立即终止任务的执行
if (dwRet2 == WAIT_OBJECT_0 + 1)
break;
}
}
AfxMessageBox("线程退出!");
return 0;
}
……
void CSample08View::OnStartEvent()
{
// 创建线程
for (int i = 0; i < 2; i++)
hEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
// 开启线程
AfxBeginThread(ThreadProc14, NULL);
// 设置事件0(开启事件)
SetEvent(hEvents[0]);
}
void CSample08View::OnEndevent()
{
// 设置事件1(结束事件)
SetEvent(hEvents[1]);
}
MFC 为事件相关处理也提供了一个CEvent 类,共包含有除构造函数外的4 个成员函数
PulseEvent()、ResetEvent()、SetEvent()和UnLock()。在功能上分别相当与
Win32 API 的PulseEvent()、ResetEvent()、SetEvent()和CloseHandle()等函
数。而构造函数则履行了原CreateEvent()函数创建事件对象的职责,其函数原型为:
CEvent(BOOL bInitiallyOwn = FALSE, BOOL bManualReset = FALSE, LPCTSTR lp
szName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );
按照此缺省设置将创建一个自动复位、初始状态为复位状态的没有名字的事件对象。封装后
的CEvent 类使用起来更加方便,图2 即展示了CEvent 类对A、B 两线程的同步过程:
DWORD WaitForMultipleObjects(
DWORD nCount, // 等待句柄数
CONST HANDLE *lpHandles, // 句柄数组首地址
BOOL fWaitAll, // 等待标志
DWORD dwMilliseconds // 等待时间间隔
);
参数nCount 指定了要等待的内核对象的数目,存放这些内核对象的数组由lpHandles 来
指向。fWaitAll 对指定的这nCount 个内核对象的两种等待方式进行了指定,为TRUE 时当所
有对象都被通知时函数才会返回,为FALSE 则只要其中任何一个得到通知就可以返回。
dwMilliseconds 在这里的作用与在WaitForSingleObject()中的作用是完全一致的。如果
等待超时,函数将返回WAIT_TIMEOUT。如果返回WAIT_OBJECT_0 到
WAIT_OBJECT_0+nCount-1 中的某个值,则说明所有指定对象的状态均为已通知状态(当
fWaitAll 为TRUE 时)或是用以减去WAIT_OBJECT_0 而得到发生通知的对象的索引(当
fWaitAll 为FALSE 时)。如果返回值在WAIT_ABANDONED_0 与
WAIT_ABANDONED_0+nCount-1 之间,则表示所有指定对象的状态均为已通知,且其中至
少有一个对象是被丢弃的互斥对象(当fWaitAll 为TRUE 时),或是用以减去WAIT_OBJECT_0
表示一个等待正常结束的互斥对象的索引(当fWaitAll 为FALSE 时)。 下面给出的代码主要
展示了对WaitForMultipleObjects()函数的使用。通过对两个事件内核对象的等待来控制线
程任务的执行与中途退出:
// 存放事件句柄的数组
HANDLE hEvents[2];
UINT ThreadProc14(LPVOID pParam)
{
// 等待开启事件
DWORD dwRet1 = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
// 如果开启事件到达则线程开始执行任务
if (dwRet1 == WAIT_OBJECT_0)
{
AfxMessageBox("线程开始工作!");
while (true)
{
for (int i = 0; i < 10000; i++);
// 在任务处理过程中等待结束事件
DWORD dwRet2 = WaitForMultipleObjects(2, hEvents, FALSE, 0);
// 如果结束事件置位则立即终止任务的执行
if (dwRet2 == WAIT_OBJECT_0 + 1)
break;
}
}
AfxMessageBox("线程退出!");
return 0;
}
……
void CSample08View::OnStartEvent()
{
// 创建线程
for (int i = 0; i < 2; i++)
hEvents[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
// 开启线程
AfxBeginThread(ThreadProc14, NULL);
// 设置事件0(开启事件)
SetEvent(hEvents[0]);
}
void CSample08View::OnEndevent()
{
// 设置事件1(结束事件)
SetEvent(hEvents[1]);
}
MFC 为事件相关处理也提供了一个CEvent 类,共包含有除构造函数外的4 个成员函数
PulseEvent()、ResetEvent()、SetEvent()和UnLock()。在功能上分别相当与
Win32 API 的PulseEvent()、ResetEvent()、SetEvent()和CloseHandle()等函
数。而构造函数则履行了原CreateEvent()函数创建事件对象的职责,其函数原型为:
CEvent(BOOL bInitiallyOwn = FALSE, BOOL bManualReset = FALSE, LPCTSTR lp
szName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );
按照此缺省设置将创建一个自动复位、初始状态为复位状态的没有名字的事件对象。封装后
的CEvent 类使用起来更加方便,图2 即展示了CEvent 类对A、B 两线程的同步过程:
更多精彩
赞助商链接