OnTimer不是多线程。
OnTimer是以SendMessage的方式发送消息到消息队列。
sendMessage必须等待对话框响应完消息后才返回。
OnTimer不是多线程。
OnTimer是以SendMessage的方式发送消息到消息队列。
sendMessage必须等待对话框响应完消息后才返回。
转载于:https://www.cnblogs.com/mycway/p/4439623.html
在MFC中我们经常需要定时读写数据,或者定时刷新界面,更新数据和状态,这就需要用到定时器,其实现函数为OnTimer,下面对其用法步骤(基于VS2010)进行简要说明:
1、在类视图中点击需要使用定时器的对话框类,在属性窗口选择消息,在下面的消息函数中选中WM_TIMER,后面选择添加OnTimer函数,如下图所示:
2、编写OnTimer函数
void CLD_PowerDlg::OnTimer(UINT_PTR nIDEvent) //定时读取数据 { switch (nIDEvent) { case 1: //定时器1处理函数,定时发送数据进行更新 { char *a=NULL; a = new char[12]; a[0]=0x55; a[1]=0xAA; a[2]=0xdc; //数据开头 a[3]=0x06; a[4]=0x00; a[5]=0x03; a[6]=0x44; a[7]=0x44; a[8]=0xcc; a[9]=0x33; a[10]=0xc3; a[11]=0x3c;//数据结尾 m_SerialPort.WriteData(a,12); a=NULL; delete a; break; } case 2: //定时器2位为状态栏时间信息 { CTime t1; t1=CTime::GetCurrentTime();//获取当前系统时间 m_Statusbar.SetPaneText(2,t1.Format("%Y-%m-%d %H:%M:%S")); //状态栏显示时间 break; } } CDialogEx::OnTimer(nIDEvent); }
3、启动定时器
SetTimer(1,1000,NULL); //参数:定时器标号,定时时间(ms)。启动定时器1,每隔1s刷新一次
4、关闭定时器
KillTimer(1); //关定时器1
定时器在VC中的使用频繁,以下讨论定义器的使用方法。
定时器的原型是:
WINUSERAPI UINT WINAPI SetTimer ( HWND hWnd , UINT nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
hWnd 是欲设置定时器的窗体句柄。定时时间到时,系统会向该窗体发送WM_TIMER消息。
nIDEvent 定时器标识符。在一个窗体内可以使用多个定时器,不同的定时器根据nIDEvent来区分。
uElapse 定时时间,单位是毫秒。
lpTimerFunc 定时器的回调函数。如果该值为NULL,定时时间到时,定时器发送的消息WM_TIMER由窗体映像该消息的函数处理;否则由回调函数处理,说白一点,这里的回调函数就是取代OnTimer的处理函数。
通常,我们在使用定时器时,只用到三个参数,即
UINT CWnd::SetTimer(
UINT nIDEvent,
UINT nElapse,
void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD)
);其实,这个函数只是MFC对API的封装,其实现函数为:
_AFXWIN_INLINE UINT CWnd::SetTimer(UINT nIDEvent, UINT nElapse,
void (CALLBACK* lpfnTimer)(HWND, UINT, UINT, DWORD))
{
ASSERT(::IsWindow(m_hWnd));
return ::SetTimer(m_hWnd, nIDEvent, nElapse,(TIMERPROC)lpfnTimer);
}由此可见,CWnd::SetTimer只是将API函数SetTimer的第一个参数设置成它自己的句柄而已。
有了上面的认识,对定时器的使用就清楚了,下面举例说明定时器的具体使用。1.打开VC,新建一基于对话框的工程,工程名为Test在对话框上添加一按钮,将其ID改为IDC_BUTTON_START,Caption改为Start. 映像该按钮的BN_CLICKED消息,void CTestDlg::OnButtonStart();
2.再在对话框上添加一按钮,ID为ID_BUTTON_STOP,Caption改为Stop,映像消息为void CTestDlg::OnButtonStop();
3.添加一个Lable,ID改为IDC_STATIC_TIME,用于记数,表明定时器函数的执行。
4.映像对话框的WM_TIMER消息,void CTestDlg::OnTimer(UINT nIDEvent);
以上的实现函数如下所示:void CTestDlg::OnButtonStart()
{
SetTimer(1,1000,NULL);//启动定时器1,定时时间是1秒
}
void CTestDlg::OnButtonStop()
{
KillTimer(1); //关闭定时器1。
}
void CTestDlg::OnTimer(UINT nIDEvent)
{
static int nTimer=0;
CString strTmp="";
strTmp.Format("Timer: %d",nTimer++);
CWnd *pWnd=GetDlgItem(IDC_STATIC_TIME);
pWnd->SetWindowText(strTmp); //在Lable中设置新值,表明定时器已经工作。
CDialog::OnTimer(nIDEvent);
}
回调函数的使用。
如果不想使用窗体的WM_TIMER消息函数处理,可以使用回调函数来取代,读者可以在上面例子的基础上,增加一个回调函数,以证实前面的讨论。
首先,定义一个回调函数,回调函数的定义必须按照如下格式。
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime );
我的实现函数如下:
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime )
{
AfxMessageBox("Timer is running!");//定时器时间到,强出一对话框,表明定时器已经运行。
}
将上面的启动函数稍做修改void CTestDlg::OnButtonStart()
{
// SetTimer(1,1000,NULL);//启动定时器1,定时时间是1秒
SetTimer(1,1000,(TIMERPROC)TimerProc);//用回调函数处理,此时对话框的消息处理函数不再处理。
}
本来我想将演示程序上传上来,可不知如何上传,所以初学者自己根据上面的操作步骤实验。
OnTimer()只是说定时触发,并不说它是“后台处理”,它仍会阻塞UI线程的;
OnTimer并不是后台线程,它同UI一个线程,所以如果占用UI线程时间过长会阻碍界面过程.
WM_TIMER的优先级比较低,对于要求实时更新的程序不适合,线程的优先级比较高,但是消耗的资源也多一些
(OnTimer)的实现是否属于多线程技术?
楼主yangchengl(爱在今生)2006-05-01 10:17:31 在 VC/MFC / 基础类 提问请解释一下,谢谢! 问题点数:10、回复次数:14Top
1 楼lisypro()回复于 2006-05-01 10:53:25 得分 1
应该是
但是不是标准的多线程Top2 楼lonely001(独行客)回复于 2006-05-01 11:01:55 得分 0
不是Top
3 楼lonely001(独行客)回复于 2006-05-01 11:03:37 得分 2
ONTIMER只是WINDOWS内置的消息发生器产生的消息,ONTIMER消息也是要排队的,这就是为什么ONTIMER很多时候并不精确的原因Top
4 楼lyl_rabbit(阿牛)回复于 2006-05-01 13:53:06 得分 0
不是,但多线程是通过时间分片实现的Top
5 楼zh2817()回复于 2006-05-01 14:44:10 得分 0
不是Top
6 楼Featured(我握着爱情的门票静静排队……)回复于 2006-05-01 15:18:08 得分 0
不是。
但比较特殊。准确地说应该是“中断”技术Top7 楼yangchengl(爱在今生)回复于 2006-05-01 18:14:35 得分 0
这样说对不对,ONTIMER实现了若干段程序的并行运行,但它并不是为各段程序创建了对应的线程,而是采用了软中断技术。Top
8 楼soaroc(会飞的猪)回复于 2006-05-01 21:28:09 得分 0
ONTIMER实现了若干段程序的并行运行
-----------------------------------------------------------------------------------
对于单CPU来说,是不可能实现程序段的并行运行的,只能是交替运行。像上面的某一楼所说的,其实它与其他的消息没有什么大的区别,只不过此消息的入队是循环的。Top9 楼yangchengl(爱在今生)回复于 2006-05-02 08:30:41 得分 0
它与其他的消息没有什么大的区别,只不过此消息的入队是循环的。
这一点解释的好。
我说的并行是指宏观上并行。在一定时间内这些程序段都获得了执行的机会。Top10 楼BXAllen()回复于 2006-05-02 20:57:03 得分 0
是单线程的!Top
11 楼BXAllen()回复于 2006-05-02 21:01:03 得分 4
mfc在cwnd中的ontimer是调用的api的settimer函数,可以在帮助文档中找到的.调用的函数是通过一个函数指针.如果是多线程的,那么是不可以通过像他定义的那样的函数指针实现的.至于函数的原型,可以自己查一下看看就明白了!
Top12 楼mjm_d(菠萝蜜多)回复于 2006-05-03 14:02:00 得分 0
不是系统级的
但是你可以用它模拟一些简单的不要求精确的用户自定义级别的线程Top13 楼roscoe(草上飞)回复于 2006-05-03 15:43:45 得分 3
不是多程技术,但应是协作式多任务,线程是抢占式多任务