一般来说,让线程休息可以用Sleep和wait...等几种方式。首先说Sleep();
这种方式就是直接让线程休眠多少时间。例如:Sleep(1000);休息1000毫秒;
把CPU的执行让给其他的线程;但是这种方式如果时间把握的不好会造成很大的浪费。比如取一个文件的时候,正好有另一个线程正在存取这个文件。你无法确定要休息多长时间,如果是主线程,你的程序界面说不定就僵死到哪里。所以Sleep()一定要有一个预知的固定的时间再用。
还有一种方式就是WaitForSingleObject和WaitForMultipleObjects;
这两个第一个是等一个信号,第二个可以等多个信号。用WaitForSingleObject这种方式可以暂时让线程等待,什么也不做,直到这个语句有返回值的时候这个线程就可以继续执行了,但是当什么时候他可以返回值,退出这个等待状态哪 ?下面我们详细讲解一下;它的原形:
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object 这个是你等的那个对象有信号;
DWORD dwMilliseconds // time-out interval 这个是你设定要等多长时间这个信号;
);
dwMilliseconds可以设置具体的时间值如:1000 就是1000毫秒。当过了1000毫秒hHandle还没有信号那,他就会返回一个WAIT_TIMEOUT值;
dwMilliseconds设定为 INFINITE ,那么它就会一直等到hHandle有信号才返回值。如果一直没有信号来,那它就一直等到你关闭程序的那一刻。呵呵;
当在规定的时间内hHandle有信号了,他会返回一个 WAIT_OBJECT_0 值。我们根据他返回的这些值就可以做出适当的判断了;下面我们做一个等待10000毫秒,
DWORD dw=WaitForSingleObject(你要等待的信号,10000); switch(dw)
{
case WAIT_OBJECT_0:
{
......这个是在规定的时间内有信号返回的值;
break;
}
case WAIT_TIMEOUT:
{
......这个是在超过规定的时间内没有信号返回的值;
break;
}
case WAIT_FAILED:
{
......这个就是当语句发生错误的时候返回的值;
break;
}
default:
{
}
下面我用一问一答的方式来给大家解释平常认为很理论的东西,其实很简单:
1、具体要问要等什么信号哪,这个信号是什么哪?这个要等的信号就是我们程序产生的一个句柄,而这个句柄指向的是一个对象;
2、激发和信号是什么关系?其实就是一个对象激发了,它就产生了一个信号,没有激发,它当然就没有信号。呵呵,不要想的太复杂;激发是系统内部的一个动作,比如你被打了一下,你就疼,打就是一个动作,就像对象被激发一样;疼就是有信号了。如果不被打一下怎么会产生疼这个信号,所以对象被激发产生了一个信号。
3、哪些对象可以产生信号?
什么情况下这些对象可以被激发产生有信号?那就是
1、线程对象,当线程结束的时候会被激发状态,没有结束的时候是未激发状态;
2、进程对象,当进程结束的时候会被激发状态,没有技术的时候是未激发状态;
3、文件对象,当一个文件或目录发生一件特别大的事情,比如:文件对象产生或删除一个子目录,产生、删除、重新命名一个文件,目录及目录的任何属性改变,最后写入时间的改变,任何安全属性的改变都会激发文件对象为激发状态;
4、Console input; 当窗口的输入缓冲区有数据可用的时候变为激发状态;
5、Event, SetEvent()可以激发产生信号,ResetEvent()可以使它无信号;
6、Mutex ; 当没有一个线程拥有它时,它就处于激发态,一旦一个线程拥有它就处于未激发态
7、 Semaphore; 当拥有Semaphore的线程的个数大于0就处于激发态,当等于0就处于未激发态;所以WaitForSingleObject可以等一个对象产生信号而返回;比如当一个线程要读一个文件,然后这个文件并不存在,你必须启动另外一个文件去下载这个文件,那在下载线程还没有结束前,你肯定是不
能读了;所以要等下载完了,下载线程结束,你的等待语句也就有信号了,也就可以读了:HANDLE hdown; 下载线程句柄;自己写下载线程;------
hdown=CreateThread(.....);
if(WAIT_OBJECT_0==WaitForSingleObject(hdown,INFINITE))
{
..........这里就可以写你要操作这个文件的语句了;
}
上面那个等待语句会一直等待直到下载线程结束,然后hdown变为有信号状态,这时程序才从休眠状态中醒过来进行下面的操作。INFINITE参数是一直等,直到有信号。
WaitForMultipleObjects和上面的类似,就是可以等多个句柄有信号而已。
DWORD WaitForMultipleObjects(
DWORD nCount, // number of handles in array这个参数是设置要等几个句柄;
CONST HANDLE *lpHandles, // object-handle array这个参数是一个句柄数组,把要等的句柄都放在这个数组里面;
BOOL bWaitAll, // wait option 如果是true,是所有的句柄有信号才返回,false是当有任何一个句柄有信号就返回;
DWORD dwMilliseconds // time-out interval 这个就是设置等待时间的;
);
返回的参数和WaitForSingleObject有一点点差异:
WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount – 1);
为什么是这样的哪? 因为是:
当bWaitAll是True的时候正常返回值是 WAIT_OBJECT_0;
当bWaitAll是false的时候正常返回值是nCount-WAIT_OBJECT_0-1 ,也就是有信号的句柄在句柄数组中的索引值
WAIT_TIMEOUT 就是在规定的时间里没有达到唤醒的等待语句的条件。比如。
当bWaitAll是false的时候一个句柄也没有信号;
当bWaitAll是True的时候一个句柄也没有信号或者不时全部的句柄都有信号;
WAIT_FAILED 就是语句出错的时候返回的值。
如果是WAIT_FAILED,可以用GetLastError()语句来得到错误信息;
WaitForSingleObject和WaitForMultipleObjects还有一个返回值由于不常用就不细说了那就是
WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount – 1)
WAIT_ABANDONED_0代表什么意思哪?就是当你等待的任何对象有Mutexes时,就会返回这种值,他也是
代表的是有Mutexes对象被激发的句柄所在的句柄数组的索引值。
这种方式就是直接让线程休眠多少时间。例如:Sleep(1000);休息1000毫秒;
把CPU的执行让给其他的线程;但是这种方式如果时间把握的不好会造成很大的浪费。比如取一个文件的时候,正好有另一个线程正在存取这个文件。你无法确定要休息多长时间,如果是主线程,你的程序界面说不定就僵死到哪里。所以Sleep()一定要有一个预知的固定的时间再用。
还有一种方式就是WaitForSingleObject和WaitForMultipleObjects;
这两个第一个是等一个信号,第二个可以等多个信号。用WaitForSingleObject这种方式可以暂时让线程等待,什么也不做,直到这个语句有返回值的时候这个线程就可以继续执行了,但是当什么时候他可以返回值,退出这个等待状态哪 ?下面我们详细讲解一下;它的原形:
DWORD WaitForSingleObject(
HANDLE hHandle, // handle to object 这个是你等的那个对象有信号;
DWORD dwMilliseconds // time-out interval 这个是你设定要等多长时间这个信号;
);
dwMilliseconds可以设置具体的时间值如:1000 就是1000毫秒。当过了1000毫秒hHandle还没有信号那,他就会返回一个WAIT_TIMEOUT值;
dwMilliseconds设定为 INFINITE ,那么它就会一直等到hHandle有信号才返回值。如果一直没有信号来,那它就一直等到你关闭程序的那一刻。呵呵;
当在规定的时间内hHandle有信号了,他会返回一个 WAIT_OBJECT_0 值。我们根据他返回的这些值就可以做出适当的判断了;下面我们做一个等待10000毫秒,
DWORD dw=WaitForSingleObject(你要等待的信号,10000); switch(dw)
{
case WAIT_OBJECT_0:
{
......这个是在规定的时间内有信号返回的值;
break;
}
case WAIT_TIMEOUT:
{
......这个是在超过规定的时间内没有信号返回的值;
break;
}
case WAIT_FAILED:
{
......这个就是当语句发生错误的时候返回的值;
break;
}
default:
{
}
下面我用一问一答的方式来给大家解释平常认为很理论的东西,其实很简单:
1、具体要问要等什么信号哪,这个信号是什么哪?这个要等的信号就是我们程序产生的一个句柄,而这个句柄指向的是一个对象;
2、激发和信号是什么关系?其实就是一个对象激发了,它就产生了一个信号,没有激发,它当然就没有信号。呵呵,不要想的太复杂;激发是系统内部的一个动作,比如你被打了一下,你就疼,打就是一个动作,就像对象被激发一样;疼就是有信号了。如果不被打一下怎么会产生疼这个信号,所以对象被激发产生了一个信号。
3、哪些对象可以产生信号?
什么情况下这些对象可以被激发产生有信号?那就是
1、线程对象,当线程结束的时候会被激发状态,没有结束的时候是未激发状态;
2、进程对象,当进程结束的时候会被激发状态,没有技术的时候是未激发状态;
3、文件对象,当一个文件或目录发生一件特别大的事情,比如:文件对象产生或删除一个子目录,产生、删除、重新命名一个文件,目录及目录的任何属性改变,最后写入时间的改变,任何安全属性的改变都会激发文件对象为激发状态;
4、Console input; 当窗口的输入缓冲区有数据可用的时候变为激发状态;
5、Event, SetEvent()可以激发产生信号,ResetEvent()可以使它无信号;
6、Mutex ; 当没有一个线程拥有它时,它就处于激发态,一旦一个线程拥有它就处于未激发态
7、 Semaphore; 当拥有Semaphore的线程的个数大于0就处于激发态,当等于0就处于未激发态;所以WaitForSingleObject可以等一个对象产生信号而返回;比如当一个线程要读一个文件,然后这个文件并不存在,你必须启动另外一个文件去下载这个文件,那在下载线程还没有结束前,你肯定是不
能读了;所以要等下载完了,下载线程结束,你的等待语句也就有信号了,也就可以读了:HANDLE hdown; 下载线程句柄;自己写下载线程;------
hdown=CreateThread(.....);
if(WAIT_OBJECT_0==WaitForSingleObject(hdown,INFINITE))
{
..........这里就可以写你要操作这个文件的语句了;
}
上面那个等待语句会一直等待直到下载线程结束,然后hdown变为有信号状态,这时程序才从休眠状态中醒过来进行下面的操作。INFINITE参数是一直等,直到有信号。
WaitForMultipleObjects和上面的类似,就是可以等多个句柄有信号而已。
DWORD WaitForMultipleObjects(
DWORD nCount, // number of handles in array这个参数是设置要等几个句柄;
CONST HANDLE *lpHandles, // object-handle array这个参数是一个句柄数组,把要等的句柄都放在这个数组里面;
BOOL bWaitAll, // wait option 如果是true,是所有的句柄有信号才返回,false是当有任何一个句柄有信号就返回;
DWORD dwMilliseconds // time-out interval 这个就是设置等待时间的;
);
返回的参数和WaitForSingleObject有一点点差异:
WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount – 1);
为什么是这样的哪? 因为是:
当bWaitAll是True的时候正常返回值是 WAIT_OBJECT_0;
当bWaitAll是false的时候正常返回值是nCount-WAIT_OBJECT_0-1 ,也就是有信号的句柄在句柄数组中的索引值
WAIT_TIMEOUT 就是在规定的时间里没有达到唤醒的等待语句的条件。比如。
当bWaitAll是false的时候一个句柄也没有信号;
当bWaitAll是True的时候一个句柄也没有信号或者不时全部的句柄都有信号;
WAIT_FAILED 就是语句出错的时候返回的值。
如果是WAIT_FAILED,可以用GetLastError()语句来得到错误信息;
WaitForSingleObject和WaitForMultipleObjects还有一个返回值由于不常用就不细说了那就是
WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount – 1)
WAIT_ABANDONED_0代表什么意思哪?就是当你等待的任何对象有Mutexes时,就会返回这种值,他也是
代表的是有Mutexes对象被激发的句柄所在的句柄数组的索引值。