我在做MFC拓展库的时候,需要在DLL里用到定时器。本打算用OnTimer,因为没有窗口类,因此只能自己发消息。
方法就是:开一个线程在线程里调用SetTimer()并自己负责接收消息,然后在定时器回调函数里处理工作。
具体如下:
1 hThreadREC = (HWND)::CreateThread(NULL,0,ThreadRecordingState,NULL,0,NULL);
2 DWORD WINAPI ThreadRecordingState(LPVOID lpParameter) { SetTimer(NULL,NULL,1000,ThreadRecordingStateproc); MSG msg; while (GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return 0; }
3 VOID CALLBACK ThreadRecordingStateproc(HWND hWnd,UINT uMsg,UINT IdEvent,DWORD dwTime) { //... }
这样做不仅繁琐,而且多开几个线程不好同步。也可能dll里的消息发送会影响到主程序里的消息循环。
因此改用Sleep()。
即单开一个线程专用于计时,如下
DWORD WINAPI ThreadTime(LPVOID lpParameter) { //根据不同功能用Sleep处理 if() { sleep(100); } else if { Sleep(2000); } //... return 0; }
但是,我是在初始化DLL是就开了这个线程,没有功能时就一直循环,会一直占用CPU,到此内存占用率变高。
此时有一种迫不得已的解决办法,即在return前加上sleep(1),即让线程去处理其它工作,虽然是1毫秒,但给了CPU喘息的机会
Sleep理解,摘自网络:
当调用Sleep函数的时候,比如Sleep(400);它告诉系统,此线程将放弃此次运行的时间片,比方说现在线程只执行了10ms,按“有关部门规定”它被唤醒一次
是要执行20ms的。这时它就说,这次机会我放弃,后面的10ms不要了。下次轮上我再叫我。 这样,系统便会将其终止,然后再一次进行调度选择。如果它运
气很好,又被选中了,系统则会查看这个线程是否处于sleep标志中。如果发现他还需要继续睡眠,则重新进行调度选择,直到选择一个有权执行的线程为止。
如果很不幸,400ms到了,但是系统很忙,调度算法在很长一段时间也没有选择到这个线程,那这么线程就很继续休眠。于是说,这个Sleep(400);将导致这
个线程会休眠大于等于400MS的时间。
系统将在大约的指定秒数内使线程不可高度。不错,如果告诉系统,想睡眠100MS,那么可以睡大约这么长的时间,但也也可能睡眠数秒或数分钟。记住,
WINDOWS不是个实时操作系统。虽然线程可能在规定的时间被唤醒,但是它能否做到,取决于系统中还有什么操作正在进行。但最好不要这么做,最好不要再初始化函数里创建线程