当开启扫描底层数据的线程后,则给底层发送数据,如果底层设备是有电的,则它将返回相应的数据给上层,如此循环执行下去,
如果某个时刻底层设备没电了(通过底层是否返回数据了来判断),则退出循环,并结束当前线程,在此期间,当线程启动时,并
开启一个定时器,来不断地刷新当前对话框的内容,如果当前设备没电了,则不再刷新。此外,上层发送数据后,底层会返回相应
的数据,这时候程序会接收到(wMsg消息,这是自定义的),紧接着就会触发OnRecv函数来接收数据并将数据送到指定的位置。
请问各位:在ScanThread线程中调用的pDlg->SetTimer(13,100,NULL);(开启13号定时器),那么它产生的WM_TIMER
消息是不是由CDlgInfo来接收啊?同样的,12号定时器的消息是不是也由CDlgInfo来接收呢?
此外我这里的SendSnmp应该是在ScanThread线程中执行,而OnRecv是在主线程执行的吧?
在我这个程序中,我不需要在ScanThread中做消息处理的吧?
UINT CDlgInfo::ScanThread( LPVOID pParam)
{
CDlgInfo *pDlg=(CDlgInfo *)pParam;
//创建一个CSingleLock对象,初始化为信号量sem
CSingleLock singlock(pDlg->sem);
//当前还未刷新界面
pDlg->m_bRefreshFlag=FALSE;
do
{
//锁信号量
singlock.Lock();
//发送snmp包到底层
pDlg->SendSnmp();
//当前设备有电,并且当前还未刷新界面,则开启定时器13,没隔100ms刷新一次
if((pDlg->m_bPowerFlag==TRUE)&&(pDlg->m_bRefreshFlag==FALSE))
{
pDlg->m_bRefreshFlag=TRUE;//已经开启定时器刷新界面了,不需要再次开启了
pDlg->SetTimer(13,100,NULL);
}
//开信号量
singlock.Unlock();
//休眠1000ms
Sleep(1000);
TRACE("Thread\n");
}
while(pDlg->m_bPowerFlag==TRUE);//当前设备还有电,则继续扫描
pDlg->KillTimer(13);//线程即将退出,将刷新界面定时器关掉,不再刷新界面了
TRACE("Thread Exit!!!!!!!!!!\n");
return 0;
}
void CDlgInfo::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch (nIDEvent)
{
case 12://一次查询结束
TRACE("time out\n");
KillTimer(12);
//查询机架信息时超时,则表示设备没电了
if(m_bJijiaFlag==TRUE)
m_bPowerFlag=FALSE;
m_bReceived=TRUE;
break;
case 13:
m_bFlashFlag=!m_bFlashFlag;
InvalidateRect(CRect(0,50,ptRect[16].right,ptRect[16].bottom),FALSE);
break;
}
CDialog::OnTimer(nIDEvent);
}
void CDlgInfo::SendSnmp()
{
//查询机架信息
m_bJijiaFlag=TRUE;
/**********这里是发送snmp包到底层,当底层收到数据之后,接着立刻返回相应的数据,
在我程序里是通过 recv消息的接收函数OnRecv来实现的*************/
if(pSnmp.sessionID==FALSE)
{
pSnmp.CreateSession(m_hWnd,wMsg);
pSnmp.sessionID=TRUE;
}
pSnmp.CreateVbl("1.3.6.1.4.1.991.1.1.0",NULL);
pSnmp.SetVbl("1.3.6.1.4.1.991.1.2.0",NULL);
pSnmp.SetVbl("1.3.6.1.4.1.991.1.3.0",NULL);
pSnmp.SetVbl("1.3.6.1.4.1.991.1.4.0",NULL);
pSnmp.CreatePdu(SNMP_PDU_GET,NULL,NULL,NULL);
pSnmp.Send(m_sIP,"public");
/******snmp发送完毕*****/
//设置当前还未收到底层的数据
m_bReceived=FALSE;
//设置12号定时器来使当时间过了200ms还未收到数据后,使m_bReceived变为真,以便下一轮的发送
KillTimer(12);
SetTimer(12,delaytime,NULL);
MSG message;
/*等待收取数据,如果数据还未收到,则等待,(过了200ms后还未收到数据后,
12号定时器,会强制使数据接收标志置为真,从而退出循环,准备下一轮发送
)*/
while(m_bReceived==FALSE)
{
Sleep(10);
}
m_bJijiaFlag=FALSE;
}
void CDlgInfo::OnRecv(WPARAM wParam, LPARAM lParam)
{
CString strIp;
CString strTemp;
int nIpin=0;//保存接收的整数值
CString str="";//保存接收的字符串
pSnmp.Receive(m_sOid,m_value);
if(pSnmp.nCount>0)//收到了数据包
{
m_bPowerFlag=TRUE;
Module[16].m_bPowerFlag=TRUE;
for(int i=0;i<pSnmp.nCount;i++)
{
//接收数据
switch(m_value[i]->syntax)
{
case SNMP_SYNTAX_INT:
//case SNMP_SYNTAX_INT32:
smiINT sNumber;
sNumber=m_value[i]->value.sNumber;
nIpin=sNumber;
str.Format("%d",sNumber);
break;
//省略若干
}
//分析数据,并将数据存放到相应的地方去(存放到相应的数组中)
}
//接收数据标志位置为真
m_bReceived=TRUE;
//关闭12号定时器,不需要判断数据包接收超时了
KillTimer(12);
}
}
7 个解决方案
#1
大家帮帮忙啊,我顶
#2
UINT CWnd::SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );事实上内部是调用API
UINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
所以,事件处理是由hWnd所代表的窗口过程处理的,也就是说是的,是由你的pDlg处理的
UINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
所以,事件处理是由hWnd所代表的窗口过程处理的,也就是说是的,是由你的pDlg处理的
#3
哦,谢谢 xiaoqiqixiao(七七),那么是这样的画,接收到WM_TIMER消息后执行的程序都是在主线程中执行喽,和ScanThread线程无关喽?
此外在我这个ScanThread线程中就不要再做消息处理了吧
此外在我这个ScanThread线程中就不要再做消息处理了吧
#4
pDlg->SetTimer(13,100,NULL);产生的定时器是由对话框pDlg来处理的
//记隹,最好不要跨线程使用CWnd*
//记隹,最好不要跨线程使用CWnd*
#5
如果你想由自己的线程处理,应该使用
VOID CALLBACK MyTimerProc( HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
);
为原型自己定义一个回调函数,然后将指针作为参数传递给最后一个参数
::SetTimer(NULL,13,1000,MyTimerProc);
VOID CALLBACK MyTimerProc( HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
);
为原型自己定义一个回调函数,然后将指针作为参数传递给最后一个参数
::SetTimer(NULL,13,1000,MyTimerProc);
#6
可以用回调函数来完成
#7
WM_TIMER消息和ScanThread线程无关
#1
大家帮帮忙啊,我顶
#2
UINT CWnd::SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );事实上内部是调用API
UINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
所以,事件处理是由hWnd所代表的窗口过程处理的,也就是说是的,是由你的pDlg处理的
UINT SetTimer(
HWND hWnd, // handle of window for timer messages
UINT nIDEvent, // timer identifier
UINT uElapse, // time-out value
TIMERPROC lpTimerFunc // address of timer procedure
);
所以,事件处理是由hWnd所代表的窗口过程处理的,也就是说是的,是由你的pDlg处理的
#3
哦,谢谢 xiaoqiqixiao(七七),那么是这样的画,接收到WM_TIMER消息后执行的程序都是在主线程中执行喽,和ScanThread线程无关喽?
此外在我这个ScanThread线程中就不要再做消息处理了吧
此外在我这个ScanThread线程中就不要再做消息处理了吧
#4
pDlg->SetTimer(13,100,NULL);产生的定时器是由对话框pDlg来处理的
//记隹,最好不要跨线程使用CWnd*
//记隹,最好不要跨线程使用CWnd*
#5
如果你想由自己的线程处理,应该使用
VOID CALLBACK MyTimerProc( HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
);
为原型自己定义一个回调函数,然后将指针作为参数传递给最后一个参数
::SetTimer(NULL,13,1000,MyTimerProc);
VOID CALLBACK MyTimerProc( HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
);
为原型自己定义一个回调函数,然后将指针作为参数传递给最后一个参数
::SetTimer(NULL,13,1000,MyTimerProc);
#6
可以用回调函数来完成
#7
WM_TIMER消息和ScanThread线程无关