多线程同步的资料--WaitForSingleObject

WaitForSingleObject的作用[转]

总结: WaitForSingleObject( HANDLE hHandle, DWORDdwMilliseconds)是主线程等待hHandle对应的线程.

在多线程的情况下,有时候我们会希望等待某一线程完成了再继续做其他事情(比如主线程等待子线程结束完之后,自己再结束),要实现这个目的,可以使用Windows API函数WaitForSingleObject,或者WaitForMultipleObjects。这两个函数都会等待Object被标为有信号(signaled)时才返回的。
那么,信号是什么呢?首先我们可以假设这里存在一个文件和两个线程,我们规定这个文件同一时刻只能被一个线程所访问打开,那么我们的线程该如何知道这个文件现在有没有被别的线程访问呢?我们可以让线程等在一个死循环里,这个循环之一在尝试打开访问这个文件,直到能够打开为止;这样做虽然可以实现目的,但是死循环会占用大量的内存,所以windows就设置了信号量。信号量的作用简单理解就是一个标志位,在我们上述的问题中,这个文件就有一个信号量,初始时我们设信号量为FALSE,而只有当信号量为FALSE时线程才可以打开访问这个文件。那么,当第一个线程到达,信号量为FALSE,线程打开文件进行访问,并将信号量置为TRUE;在第一个线程在访问文件时,第二个线程到来,此时信号量仍未TRUE,所以第二个线程等待,这个等待的过程就是WaitForSingleObject。WaitForSingleObject在等待的过程中会进入一个非常高效的沉睡等待状态,只占用极少的CPU时间片。

WaitForSingleObject()
1. 格式

DWORD WaitForSingleObject( HANDLE hHandle, DWORDdwMilliseconds);

有两个参数,分别是THandle和Timeout(毫秒单位)。

如果想要等待一条线程,那么你需要指定线程的Handle,以及相应的Timeout时间。当然,如果你想无限等待下去,Timeout参数可以指定系统常量INFINITE。

2. 使用对象

它可以等待如下几种类型的对象:

Event,Mutex,Semaphore,Process,Thread 

3. 返回类型

有三种返回类型:

WAIT_OBJECT_0, 表示等待的对象有信号(对线程来说,表示执行结束);

 WAIT_TIMEOUT, 表示等待指定时间内,对象一直没有信号(线程没执行完);

WAIT_ABANDONED 表示对象有信号,但还是不能执行  一般是因为未获取到锁或其他原因

代码例如下:

复制代码

 1 // ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
 2 //
 3  
 4 #include "stdafx.h"
 5 #include "stdio.h"
 6 #include "windows.h"
 7 #include <iostream>
 8 using namespace std;
 9  
10 int i = 0;
11 DWORD WINAPI FunProc(LPVOID lpParameter);
12  
13 DWORD WINAPI FunProc(LPVOID lpParameter)
14 {
15     for (; i < 10; i++)
16     {
17         if (!(i % 10))
18             cout << endl;
19         else
20             cout << i << endl;
21     }
22     return 0;
23 }
24  
25 void main()
26 {
27     cout << i << endl;
28     HANDLE hThread;
29     hThread = CreateThread(NULL, 0, FunProc, NULL, 0, NULL);
30     DWORD dwRet = WaitForSingleObject(hThread, 1);
31     if (dwRet == WAIT_OBJECT_0)
32     {
33         cout<< "创建的线程执行结束" << endl;
34     }
35     if (dwRet == WAIT_TIMEOUT)
36     {
37         cout<< "等待超时" << endl;
38     }
39     if (dwRet == WAIT_ABANDONED)
40     {
41         cout<< "Abandoned" << endl;
42     }
43     CloseHandle(hThread);
44     system("pause");
45 }
46  

复制代码


结果为:

 

 这段代码中,首先在开始定义一个变量  i  为  0 ,然后在主函数中先将其输出便有了结果中第一行的  0 。

之后我们开启线程,进入线程函数FunProc,在FunProc中将  i++ 对 10 取余输出,一直到 i > 10 结束循环,线程结束,这是返回给WaitForSingleObject的结果为WAIT_OBJECT_0,表示线程正常结束,并将结果输出。

这其中WaitForSingleObject的效果就相当于一个关卡,只有返回给了WaitForSingleObject结果程序才能继续执行,当然线程不一定能正常执行结束,也可能会出现:

 

 这就是未能等到线程结束信号量的等待时间就耗光了。我们也可以将WaitForSingleObject的第二个参数设置为 INFINITE,就可以一直等待。

线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回(那区别在哪呢? 一个是有信号的主动返回,另一个是没信号的超时被动返回)
————————————————
版权声明:本文为CSDN博主「LL596214569」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/LL596214569/article/details/81088862

这个帖子里讲了使用超时时间的作用:

解决方案:
要解决等待并刷新,可以
重复
ret:= WaitforSingleObject(ProcessInfo.hProcess ,100); //等待
Application.ProcessMessages; 
直到ret&lt; Wait_Timeout; 
即每次只等待很短的时间,然后刷新界面,如果程序没有运行完成,则继续等待,否则
跳出。

另一篇文章,里面讲到了一个比较有用的功能:也讲了获取进程的一些方法

WaitForSingleObject的用法-(判断一个程序是否结束)

https://blog.csdn.net/iteye_3224/article/details/82123379

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在VC中,可以使用三种多线程同步方法,分别是临界区(CriticalSection)、事件(Event)、互斥体(Mutex)。下面是一个使用这三种方法的多线程程序的示例: #include <windows.h> #include <iostream> using namespace std; int g_iCount = 0; CRITICAL_SECTION g_cs; //定义临界区 HANDLE g_hEvent; //定义事件句柄 HANDLE g_hMutex; //定义互斥体句柄 DWORD WINAPI ThreadFunc(LPVOID lpParam) { for (int i = 0; i < 100000; i++) { EnterCriticalSection(&g_cs); //进入临界区 g_iCount++; //临界区内进行操作 LeaveCriticalSection(&g_cs); //退出临界区 SetEvent(g_hEvent); //设置事件 WaitForSingleObject(g_hMutex, INFINITE); //等待互斥体 g_iCount--; //互斥体中进行操作 ReleaseMutex(g_hMutex); //释放互斥体 } return 0; } int main(int argc, char* argv[]) { HANDLE hThread[2]; DWORD dwThreadId[2]; InitializeCriticalSection(&g_cs); //初始化临界区 g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); //创建事件 g_hMutex = CreateMutex(NULL, FALSE, NULL); //创建互斥体 for (int i = 0; i < 2; i++) { hThread[i] = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &dwThreadId[i]); //创建线程 } for (int i = 0; i < 2; i++) { WaitForSingleObject(hThread[i], INFINITE); //等待线程结束 } cout << "iCount = " << g_iCount << endl; DeleteCriticalSection(&g_cs); //删除临界区 CloseHandle(g_hEvent); //关闭事件句柄 CloseHandle(g_hMutex); //关闭互斥体句柄 return 0; } 上面的程序中,首先定义了一个全局变量g_iCount,用于计数。然后定义了一个临界区g_cs、一个事件句柄g_hEvent、一个互斥体句柄g_hMutex。在主函数中,首先初始化临界区、创建事件句柄、创建互斥体句柄。然后创建两个线程,每个线程都调用ThreadFunc函数。在ThreadFunc函数中,通过EnterCriticalSection和LeaveCriticalSection进入和退出临界区。通过SetEvent设置事件,并通过WaitForSingleObject等待互斥体。通过ReleaseMutex释放互斥体。最后主函数等待两个线程结束,并输出计数结果。最后删除临界区,关闭事件句柄和互斥体句柄。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值