SetTimer以后定时器为什么没有马上执行???急,在线等待!!!

时间:2020-12-11 23:33:14
目的:在弹出对话框的时候,有做一些初始化操作(打开数据库)。主对话框有一个进度条进行进度显示。控制弹出的对话框InitDialog()结束时候,进度条刚好填满。

方法:

BOOL CDlgCustomer::OnInitDialog() 
{
CDialog::OnInitDialog();

// TODO: Add extra initialization here

((CMainFrame*)AfxGetMainWnd())->OnProgress();
//OnProgress()执行SetTimer(1,1000,NULL);
         

         //以下是打开数据库及相关操作

m_pBankSet=new CBankSet;

m_pBankSet->m_strSort="BANK_ID";
if (m_pBankSet->IsOpen())
m_pBankSet->Close();
m_pBankSet->Open();
if (!m_pBankSet->IsBOF())
m_pBankSet->MoveFirst();


while (!m_pBankSet->IsEOF())
{//将bank表中内容逐条显示在combobox中
m_comboBank.AddString(m_pBankSet->m_BANK_NAME);
m_pBankSet->MoveNext();


}

if (m_pBankSet->IsOpen())
m_pBankSet->Close();
if (m_pBankSet)
delete m_pBankSet;

((CMainFrame*)AfxGetMainWnd())->EndProgress();
         //EndProgress执行m_Progress.SetPos(100);指向进度条末端, KillTimer(1);

return TRUE;
}

void CMainFrame::OnTimer(UINT nIDEvent) 
{
// TODO: Add your message handler code here and/or call default

if (nIDEvent==1)
{
m_Progress.StepIt();
}
}

理论上应该SetTimer后进度条就一直增长,直到执行EnProgress(),这时候InitDialog完毕,进度条也指向末端。

但问题是,在执行打开数据库的时候,进度条一直没有动:(当我把网线拔了后,发现进度条要到弹出输入数据库DSN,UID,PWD的那个对话框(因为连接不上,所以弹出该对话框)后,才开始增长。

也就是说并不是一SetTimer就创建新进程,可以执行OnTimer,有时候几十秒以后进度条才开始动。为什么会这样?

大侠们快来帮忙啊。或者提供你们解决该类问题的方法。
马上给分,不够可以再加!!!

27 个解决方案

#1


SetTimer建立定时器后会发送WM_TIMER消息,但问题是该消息仅仅是放到消息队列中排队,并不会马上被执行,因为消息对列中可能还有其它消息等待执行,你可以试试通过建立另外一个线程的方式来实现你的目的。

#2


去掉nIDEvent == 1试试;
OnTimer一般是第一个Click后才执行,如果你定义Click时间是一秒,它就在定时器创建后一秒被激活

#3


就算排队一般时间也不会很长,计数器的优先级还是很高的,属于很重要(宝贵)的资源,所以msdn要求尽可能少用

#4


同意dominolili(domino) ,settimer后并不会立即进入ontimer

#5


你的主线程正在执行 OnInitDialog () 不可能去执行onTimer.
你只能直接调用m_Progress.StepIt();

#6


SetTimer建立定时器后会发送WM_TIMER消息,但问题是该消息仅仅是放到消息队列中排队,并不会马上被执行,因为消息对列中可能还有其它消息等待执行,你可以试试通过建立另外一个线程的方式来实现你的目的。

#7


same to what sans(sans) said

#8


to dominolili:并不是第一个Click后才执行的,有时候要过几十秒。好像必须执行打开数据库的操作后才执行。



我的本意是如果打开数据库比较慢(或者发生网络故障),有个进度条可以显示进度,不至于让人以为死机了。但是,如果Init完成后再显示,就没有达到预期效果了。

建立另一个线程具体怎么做,能不能给个例子。

谢谢!!!


#9


昨天(13日)VC知识论坛中就有(Panic的),你自己去看吧!

#10


没搜索到啊。题目叫什么名字?

#11


先调用一次过程
settimer
ontimer()
{
调用过程
}

#12


To ClickMore 你误会了。我知道Ontimer 要一个Click后执行的。

但是好像打开数据库的优先级比Ontimer大。所以,总是要先执行完打开数据库后才开始计数的。  照理应该0.1秒后开始计数,但是有时候要过几十秒,等数据库操作完毕后才开始计数。


#13


如何通过进程控制MainFrame中的进度条啊?我用
HWND hWnd=GetSafeHwnd();
AfxBeginThread(ThreadProc,hWnd,THREAD_PRIORITY_NORMAL);


UINT ThreadProc(LPVOID param)
{
while (((CMainFrame*)AfxGetMainWnd())->m_Progress.GetPos()<90)
{
((CMainFrame*)AfxGetMainWnd())->m_Progress.StepIt();
Sleep(100);
}

return 0;

}

会出错。怎么用进程对对话框中的控件进行操作啊?Help!!!!

#14


工作线程不要直接调用另外线程的界面,最好向界面发送一个消息,在界面的消息处理中做事情。

UINT ThreadProc(LPVOID param)
{
while (((CMainFrame*)AfxGetMainWnd())->m_Progress.GetPos()<90)
{
((CMainFrame*)AfxGetMainWnd())->PostMessage(WM_USER+1,0,0);
Sleep(100);
}

return 0;

}

然后在MainFrame中响应WM_USER+1,调用m_Progress.StepIt();

#15


但是在执行(((CMainFrame*)AfxGetMainWnd())->m_Progress.GetPos()的时候就出错了。

#16


最好的效果是采用多现成;
或者是控件

#17


发现错误在哪里了。

竟然在HWND hWnd=GetSafeHwnd();
AfxBeginThread(ThreadProc,hWnd,THREAD_PRIORITY_NORMAL);//这一句出错


CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
int nPriority, UINT nStackSize, DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
#ifndef _MT
pfnThreadProc;
pParam;
nPriority;
nStackSize;
dwCreateFlags;
lpSecurityAttrs;

return NULL;
#else
ASSERT(pfnThreadProc != NULL);

CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam);
ASSERT_VALID(pThread);

if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,
lpSecurityAttrs))
{
pThread->Delete();
return NULL;
}
VERIFY(pThread->SetThreadPriority(nPriority));
if (!(dwCreateFlags & CREATE_SUSPENDED))
VERIFY(pThread->ResumeThread() != (DWORD)-1);//调试到这个地方出错,不知道为什么。

return pThread;
#endif //!_MT)
}

#18


为什么HWND hWnd=GetSafeHwnd();
AfxBeginThread(ThreadProc,hWnd,THREAD_PRIORITY_NORMAL);会出错啊?

没道理啊。


我的项目是单文档的。在主窗口分割为两个子窗口,和这有关系吗?

#19


提示unhandled exception in **.exe(MFC42D.DLL):0xc0000005 Acess Violation


_AFXWIN_INLINE DWORD CWinThread::ResumeThread()
{ ASSERT(m_hThread != NULL); //在这调试出错了,为什么啊??

return ::ResumeThread(m_hThread); }

大侠们快救命啊!!!

#20


http://www.codeguru.com/controls/WaitDialog.shtml
你可以试试。不过只是另一种解决方案

#21


郁闷啊。~~:(

#22


现在我改成用另一个线程发送消息给主进程,由主进程处理了。但这个方法和SetTimer一样。进程发的消息也是在消息队列中,要执行完数据库的操作后才响应我定义的消息。这样,还是不能达到同时进程条在数据库操作的同时增长。


怎么使进程条和数据库操作同时运行?

#23


主线程被阻塞,不会响应Message,控件不会刷新
把数据库操作移到新线程中

#24


同意: robothn(雷鸟)

#25


to robothn:

    数据库操作是用CRecordSet.
try 
{
m_pMySet->Open();
}

catch (CDBException *e){}

如果不是在主进程中执行m_pMySet->Open,我主进程中还要用到m_pMySet怎么办?

#26


当然是新线程使用主线程的m_pMySet

AfxBeginThread(ThreadProc,hWnd,THREAD_PRIORITY_NORMAL);
UINT ThreadProc(LPVOID param);
AfxBeginThread()的第二个参数就是给ThreadProc传参的,你传个hWnd有什么用?

改为:
AfxBeginThread(ThreadProc,m_pMySet,THREAD_PRIORITY_NORMAL);
...
UINT ThreadProc(LPVOID param)
{
  CRecordSet* pset = (CRecordSet*)param;
  ...
}

#27


行了,谢谢各位大侠,尤其是robothn

#1


SetTimer建立定时器后会发送WM_TIMER消息,但问题是该消息仅仅是放到消息队列中排队,并不会马上被执行,因为消息对列中可能还有其它消息等待执行,你可以试试通过建立另外一个线程的方式来实现你的目的。

#2


去掉nIDEvent == 1试试;
OnTimer一般是第一个Click后才执行,如果你定义Click时间是一秒,它就在定时器创建后一秒被激活

#3


就算排队一般时间也不会很长,计数器的优先级还是很高的,属于很重要(宝贵)的资源,所以msdn要求尽可能少用

#4


同意dominolili(domino) ,settimer后并不会立即进入ontimer

#5


你的主线程正在执行 OnInitDialog () 不可能去执行onTimer.
你只能直接调用m_Progress.StepIt();

#6


SetTimer建立定时器后会发送WM_TIMER消息,但问题是该消息仅仅是放到消息队列中排队,并不会马上被执行,因为消息对列中可能还有其它消息等待执行,你可以试试通过建立另外一个线程的方式来实现你的目的。

#7


same to what sans(sans) said

#8


to dominolili:并不是第一个Click后才执行的,有时候要过几十秒。好像必须执行打开数据库的操作后才执行。



我的本意是如果打开数据库比较慢(或者发生网络故障),有个进度条可以显示进度,不至于让人以为死机了。但是,如果Init完成后再显示,就没有达到预期效果了。

建立另一个线程具体怎么做,能不能给个例子。

谢谢!!!


#9


昨天(13日)VC知识论坛中就有(Panic的),你自己去看吧!

#10


没搜索到啊。题目叫什么名字?

#11


先调用一次过程
settimer
ontimer()
{
调用过程
}

#12


To ClickMore 你误会了。我知道Ontimer 要一个Click后执行的。

但是好像打开数据库的优先级比Ontimer大。所以,总是要先执行完打开数据库后才开始计数的。  照理应该0.1秒后开始计数,但是有时候要过几十秒,等数据库操作完毕后才开始计数。


#13


如何通过进程控制MainFrame中的进度条啊?我用
HWND hWnd=GetSafeHwnd();
AfxBeginThread(ThreadProc,hWnd,THREAD_PRIORITY_NORMAL);


UINT ThreadProc(LPVOID param)
{
while (((CMainFrame*)AfxGetMainWnd())->m_Progress.GetPos()<90)
{
((CMainFrame*)AfxGetMainWnd())->m_Progress.StepIt();
Sleep(100);
}

return 0;

}

会出错。怎么用进程对对话框中的控件进行操作啊?Help!!!!

#14


工作线程不要直接调用另外线程的界面,最好向界面发送一个消息,在界面的消息处理中做事情。

UINT ThreadProc(LPVOID param)
{
while (((CMainFrame*)AfxGetMainWnd())->m_Progress.GetPos()<90)
{
((CMainFrame*)AfxGetMainWnd())->PostMessage(WM_USER+1,0,0);
Sleep(100);
}

return 0;

}

然后在MainFrame中响应WM_USER+1,调用m_Progress.StepIt();

#15


但是在执行(((CMainFrame*)AfxGetMainWnd())->m_Progress.GetPos()的时候就出错了。

#16


最好的效果是采用多现成;
或者是控件

#17


发现错误在哪里了。

竟然在HWND hWnd=GetSafeHwnd();
AfxBeginThread(ThreadProc,hWnd,THREAD_PRIORITY_NORMAL);//这一句出错


CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
int nPriority, UINT nStackSize, DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
#ifndef _MT
pfnThreadProc;
pParam;
nPriority;
nStackSize;
dwCreateFlags;
lpSecurityAttrs;

return NULL;
#else
ASSERT(pfnThreadProc != NULL);

CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam);
ASSERT_VALID(pThread);

if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,
lpSecurityAttrs))
{
pThread->Delete();
return NULL;
}
VERIFY(pThread->SetThreadPriority(nPriority));
if (!(dwCreateFlags & CREATE_SUSPENDED))
VERIFY(pThread->ResumeThread() != (DWORD)-1);//调试到这个地方出错,不知道为什么。

return pThread;
#endif //!_MT)
}

#18


为什么HWND hWnd=GetSafeHwnd();
AfxBeginThread(ThreadProc,hWnd,THREAD_PRIORITY_NORMAL);会出错啊?

没道理啊。


我的项目是单文档的。在主窗口分割为两个子窗口,和这有关系吗?

#19


提示unhandled exception in **.exe(MFC42D.DLL):0xc0000005 Acess Violation


_AFXWIN_INLINE DWORD CWinThread::ResumeThread()
{ ASSERT(m_hThread != NULL); //在这调试出错了,为什么啊??

return ::ResumeThread(m_hThread); }

大侠们快救命啊!!!

#20


http://www.codeguru.com/controls/WaitDialog.shtml
你可以试试。不过只是另一种解决方案

#21


郁闷啊。~~:(

#22


现在我改成用另一个线程发送消息给主进程,由主进程处理了。但这个方法和SetTimer一样。进程发的消息也是在消息队列中,要执行完数据库的操作后才响应我定义的消息。这样,还是不能达到同时进程条在数据库操作的同时增长。


怎么使进程条和数据库操作同时运行?

#23


主线程被阻塞,不会响应Message,控件不会刷新
把数据库操作移到新线程中

#24


同意: robothn(雷鸟)

#25


to robothn:

    数据库操作是用CRecordSet.
try 
{
m_pMySet->Open();
}

catch (CDBException *e){}

如果不是在主进程中执行m_pMySet->Open,我主进程中还要用到m_pMySet怎么办?

#26


当然是新线程使用主线程的m_pMySet

AfxBeginThread(ThreadProc,hWnd,THREAD_PRIORITY_NORMAL);
UINT ThreadProc(LPVOID param);
AfxBeginThread()的第二个参数就是给ThreadProc传参的,你传个hWnd有什么用?

改为:
AfxBeginThread(ThreadProc,m_pMySet,THREAD_PRIORITY_NORMAL);
...
UINT ThreadProc(LPVOID param)
{
  CRecordSet* pset = (CRecordSet*)param;
  ...
}

#27


行了,谢谢各位大侠,尤其是robothn