重工电子论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 9823|回复: 3
打印 上一主题 下一主题

[VC] 【MFC多线程】多线程里面WM_TIMER消息的响应

[复制链接]

299

主题

684

帖子

7009

积分

学生管理组

Rank: 8Rank: 8

积分
7009
跳转到指定楼层
楼主
发表于 2015-6-16 02:39:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在项目中遇到的一系列用 VC多线程问题 总目录贴: (先留着 以后填上)

写在前面话:
该问题是我近期在实际上位机程序项目中遇到的,我把该问题重点提取出来,并且附上我自己的理解和解决思路。
特此记录下来为以后查阅起来做参考。


开发环境VC6.0  SP6  
运行环境XP SP3


问题描述:

一个基于对话框的程序:
下面是我的主要代码:
[C++] syntaxhighlighter_viewsource syntaxhighlighter_copycode
void CExample2Dlg::OnButton1() 
{
	// TODO: Add your control notification handler code here3
	sum =0;
	uiTimer = SetTimer(1,10,NULL);
	AfxBeginThread(MyThread1,this);
}


UINT CExample2Dlg::MyThread1(void *param)
{
	CExample2Dlg *Dlg=(CExample2Dlg *)param;
	Sleep(105);

	CString tmp;
	tmp.Format("%d",Dlg->sum);
	AfxMessageBox(tmp);
	return 0;
}

void CExample2Dlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	sum++;
	CDialog::OnTimer(nIDEvent);
}



目的就是在按钮Button1点下过后,就开起定时器,在OnTimer里面做计数,再开启线程,然后在线程里面Sleep(105),然后再用AfxMessageBox(tmp);的方式显示出在Sleep(105)这段时间里面到底响应了多少次OnTimer;

我这里定时器周期设置的是10ms,我在线程里面Sleep(105),按照道理说,应该响应10次OnTimer,但是实际情况确是只响应了6,7次 这个次数不定 我想问问为什么?

我认为以上原因可能是启动线程需要一定时间,至于什么时候启动可能是操作系统自己分配的,

那么我把上面代码变一下,变成我在线程里面启动定时器,就不存在启动线程需要的时间干扰了吧

[C++] syntaxhighlighter_viewsource syntaxhighlighter_copycode
void CExample2Dlg::OnButton1() 
{
	// TODO: Add your control notification handler code here3

	AfxBeginThread(MyThread1,this);
}


UINT CExample2Dlg::MyThread1(void *param)
{
	CExample2Dlg *Dlg=(CExample2Dlg *)param;
	Dlg->start();
	Sleep(110);

	CString tmp;
	tmp.Format("%d",Dlg->sum);
	AfxMessageBox(tmp);
	return 0;
}

void CExample2Dlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	sum++;
	CDialog::OnTimer(nIDEvent);
}


void CExample2Dlg::start()
{
	sum =0;
	uiTimer = SetTimer(1,10,NULL);
}



问题提出:

整个流程就是点击botton 就启动线程 然后线程里面启动定时器,然后线程sleep,让OnTimer响应,等线程Sleep完了,再输出响应了多少次OnTimer,可是这样 也就显示响应了7次,按理说,应该响应10次的,这是为什么?



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

299

主题

684

帖子

7009

积分

学生管理组

Rank: 8Rank: 8

积分
7009
沙发
 楼主| 发表于 2015-6-16 02:46:46 | 只看该作者
问题分析以及解决

根据MSDN上面的解释,可以找到以下文字:
http://msdn.microsoft.com/en-us/ ... 44906(v=vs.85).aspx

The time-out value, in milliseconds.
If uElapse is less than USER_TIMER_MINIMUM (0x0000000A), the timeout is set to USER_TIMER_MINIMUM. If uElapse is greater than USER_TIMER_MAXIMUM (0x7FFFFFFF), the timeout is set to USER_TIMER_MAXIMUM.


Timer使用的时间中断,
Windows中每隔1/18秒触发一个时钟中断,所以,Timer的定时精度1000/18
SetTimer线程优先级别很低,要等其它的线程执行完后运行它,所以精度度很差,用于要求不高的场合。如果要求高的话可以采用多媒体定时或更高级别的定时方法。

WM_TIMER消息的优先级比较低,当消息队列里没有其它待处理的高优先级的消息的时候,才会去处理它,如果你的应用程序很繁忙,那么延迟就会很明显。
The WM_TIMER message is a low-priority message. The GetMessage and PeekMessage functions post this message only when no other higher-priority messages are in the thread's message queue.  

可以用以下代码验证:
[C++] syntaxhighlighter_viewsource syntaxhighlighter_copycode
#include <windows.h>

static int g_nCount = 0;
#define Timer_Once_Time (1000/18)
DWORD WINAPI threadFunc (LPVOID pArg)
{
	Sleep(100*Timer_Once_Time);
	printf("%d",*((int*)pArg));
	return 0;
}

void CALLBACK TimerProc(HWND hwnd, UINT message, UINT timerID, DWORD time) 
{ 
	g_nCount++;
	printf("%d\n",g_nCount);
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hThread;
	hThread = CreateThread (NULL, 0, threadFunc, &g_nCount, 0, NULL );
	

	SetTimer(NULL, 0, 10*Timer_Once_Time, TimerProc); 
	// 主消息循环:
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		//if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}

	return (int) msg.wParam;
}

回复 支持 反对

使用道具 举报

2

主题

26

帖子

126

积分

超级版主

Rank: 8Rank: 8

积分
126
板凳
发表于 2015-6-16 15:11:00 | 只看该作者
用时间戳最好,每次获取当前时间与时间戳比较

精度有各种选择,和选择的机制和数据类型有关

可以做到ms甚至ns级的定时
回复 支持 反对

使用道具 举报

299

主题

684

帖子

7009

积分

学生管理组

Rank: 8Rank: 8

积分
7009
地板
 楼主| 发表于 2015-6-16 23:29:06 | 只看该作者
周鹏 发表于 2015-6-16 15:11
用时间戳最好,每次获取当前时间与时间戳比较

精度有各种选择,和选择的机制和数据类型有关

时间戳 是什么东西哟?  我没见过也。。。

我为了更精确的定时,往往采用优先级高的定时器,只不过这次没有用到, 也解决了,用户要求没有这么高。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|cqutlab ( 渝ICP备15004556号

GMT+8, 2024-12-22 17:19 , Processed in 0.178688 second(s), 28 queries .

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表