Calling OnIdle() within OnTimer()
kvasilak@cyberoptics.com Friday, January 03, 1997 Environment: VC++ 4.1, Win 95 I have an app that is doing data analysis and basically is grabbing data as fast as it can, analyzing it and displaying the results as fast as possible. I am using an OnTimer() event which works well for the most part. The problem is that the data analysis needs to happen as fast as possible. However if the timer period is equal to or less than the execution time of the OnTimer() function, there is no idle time and OnIdle() never gets called. This means my toolbars don't update and messageboxes take a very long time to appear. If the Timer period is too long my customers complain, LOUDLY. Also I need to run this app on machines with different speeds, so I can't optimize the time-out very well. I added the folowing code in hopes of solving the lack of idle time processing, unfortunately it causes an exception if a toolbar is moved. Is there any reason this should not work? The OnIdle Call; LONG lIdle = 0; while (AfxGetApp()->OnIdle(lIdle++)); The Error Message; 'CDC:DrawDragRect(const tgaRect * 0x0066f678 unhandled exception in Build.exe (MFC40D.DLL) 0x00000005: Access violation ' The function call that caused the exception, from the debugger; CDC::DrawDragRect( const tagRECT * 0x0066f678 {top=33 bottom=62 left=19 right=439}, tagSIZE {...}, const tagRECT * 0x00681a3c {top=33 bottom=62 left=16 right=436}, tagSIZE {...}, CBrush * 0x00683310 {CGdiObject}, CBrush * 0x00683310 {CGdiObject}) line 203 Keith V
Tony Headford -- tony@ktgroup.co.uk Monday, January 06, 1997 Hi Keith, I've always thought that CWinApp::OnIdle was something that you never called explicitly (except from inside your own CMyApp::OnIdle), it was just a means for you to perform background processing, and for the MFC to do memory cleans ups and UI updates (correct me if I'm wrong). It sounds like perhaps you should be using a separate thread to do your data analysis, which then may negate the need to have a timer. Hope this helps, Tony. At 13:56 03/01/97 -0600, you wrote: > Environment: VC++ 4.1, Win 95 > > I have an app that is doing data analysis and basically is grabbing > data as fast as it can, analyzing it and displaying the results as > fast as possible. > I am using an OnTimer() event which works well for the most part. > > The problem is that the data analysis needs to happen as fast as > possible. However if the timer period is equal to or less than the > execution time of the OnTimer() function, there is no idle time and > OnIdle() never gets called. This means my toolbars don't update and > messageboxes take a very long time to appear. > If the Timer period is too long my customers complain, LOUDLY. > Also I need to run this app on machines with different speeds, so I > can't optimize the time-out very well. > > I added the folowing code in hopes of solving the lack of idle time > processing, unfortunately it causes an exception if a toolbar is > moved. Is there any reason this should not work? > > > The OnIdle Call; > > LONG lIdle = 0; > while (AfxGetApp()->OnIdle(lIdle++)); > > The Error Message; > > 'CDC:DrawDragRect(const tgaRect * 0x0066f678 unhandled exception in > Build.exe (MFC40D.DLL) 0x00000005: Access violation ' > > The function call that caused the exception, from the debugger; > > CDC::DrawDragRect( > const tagRECT * 0x0066f678 {top=33 bottom=62 left=19 right=439}, > tagSIZE {...}, > const tagRECT * 0x00681a3c {top=33 bottom=62 left=16 right=436}, > tagSIZE {...}, > CBrush * 0x00683310 {CGdiObject}, > CBrush * 0x00683310 {CGdiObject}) line 203 > > Keith V > > ________________________________________ Tony Headford - Software Developer RMS Services Ltd email: tony@ktgroup.co.uk
David Razzetti -- raz@jump-jet.demon.co.uk Monday, January 06, 1997 On Fri, 3 Jan 1997 13:56:15 -0600, you wrote: > Environment: VC++ 4.1, Win 95 > =20 > I have an app that is doing data analysis and basically is grabbing= =20 > data as fast as it can, analyzing it and displaying the results as=20 > fast as possible.=20 > I am using an OnTimer() event which works well for the most part. > =20 > The problem is that the data analysis needs to happen as fast as=20 > possible. However if the timer period is equal to or less than the=20 > execution time of the OnTimer() function, there is no idle time and= =20 > OnIdle() never gets called. This means my toolbars don't update and= =20 > messageboxes take a very long time to appear. > If the Timer period is too long my customers complain, LOUDLY. > Also I need to run this app on machines with different speeds, so I= =20 > can't optimize the time-out very well. > =20 ....snip Is all of the above going on within a single thread ? If it is, then surely, your life would be a lot easier if you divided the work between two threads. By creating a separate worker thread to grab and display the data, you leave the main thread to handle the user interface. As long as the thread priorities are the same, the operating system scheduler should handle the problem of dividing the processor's time between data acquisition and the responsiveness of the user interface. I have no idea as to the reason for your problem with the OnIdle call. Hope the above helps ... Dave Razzetti raz@jump-jet.demon.co.uk
kvasilak@cyberoptics.com Tuesday, January 07, 1997 There seems to be a consensus a that I need to create a worker thread. Unfortunately my attempt at creating a worker thread uncovered a problem. I have a Graph OCX placed on a dialogbar, the worker thread cannot send data to that OCX, note that the worker thread CAN send data to an OCX that is on a FormView and FormView code can send data to the DialogBar OCX. Go Figure. What I do is this, remember this works from a FormView but not from a worker thread; This function, a member of my DialogBar class, returns a pointer to the Graph OCX on the DialogBar. CCSGraph *CBarGraph::GetChart() { CCSGraph *pGraph; pGraph = (CCSGraph *)GetDlgItem(IDC_CSGRAPHCTRL2); return pGraph; } Here part of my thread code UINT MyThread(LPVOID pParam ) { VARIANT vtRed; ---snip CDillyApp *pMyApp = ((CDillyApp *)AfxGetApp()); CCSGraph *MyGraph = pMyApp->m_pMyDlg->GetChart(); MyGraph->SetPlotReadings( vtRed); MyGraph->m_Graph->Refresh(); ---snip } During the call to SetPlotReadings I get an assertion in Winocc.cpp. Again this only happens if the OCX is on a DialogBar and called from a seperate thread. void AFX_CDECL CWnd::SetProperty(DISPID dwDispID, VARTYPE vtProp, ...) { ASSERT(m_pCtrlSite != NULL);// not an OLE control (not yet, at least) ----snip What is really weird is during a trace GetChart() has a vaild pointer, pGraph, until it returns to the worker thread, then pGraph has changed. Of course I have tried graphing from GetChart() with the same results... Keith V KVasilak@cyberOptics.com ______________________________ Reply Separator _________________________________ Subject: Re: Calling OnIdle() within OnTimer() Author: David Razzettiat INTERNET Date: 1/6/97 9:44 PM On Fri, 3 Jan 1997 13:56:15 -0600, you wrote: > Environment: VC++ 4.1, Win 95 > > I have an app that is doing data analysis and basically is grabbing > data as fast as it can, analyzing it and displaying the results as > fast as possible. > I am using an OnTimer() event which works well for the most part. > > The problem is that the data analysis needs to happen as fast as > possible. However if the timer period is equal to or less than the > execution time of the OnTimer() function, there is no idle time and > OnIdle() never gets called. This means my toolbars don't update and > messageboxes take a very long time to appear. > If the Timer period is too long my customers complain, LOUDLY. > Also I need to run this app on machines with different speeds, so I > can't optimize the time-out very well. > ....snip Is all of the above going on within a single thread ? If it is, then surely, your life would be a lot easier if you divided the work between two threads. By creating a separate worker thread to grab and display the data, you leave the main thread to handle the user interface. As long as the thread priorities are the same, the operating system scheduler should handle the problem of dividing the processor's time between data acquisition and the responsiveness of the user interface. I have no idea as to the reason for your problem with the OnIdle call. Hope the above helps ... Dave Razzetti raz@jump-jet.demon.co.uk
Mike Blaszczak -- mikeblas@nwlink.com Wednesday, January 08, 1997 At 13:56 1/3/97 -0600, kvasilak@cyberoptics.com wrote: > Environment: VC++ 4.1, Win 95 > I have an app that is doing data analysis and basically is grabbing > data as fast as it can, analyzing it and displaying the results as > fast as possible. > I am using an OnTimer() event which works well for the most part. This isn't a very good approach. If other applications on the system become busy, you won't send OnTimer() messages regularly and you'll end up not responding to both the messages and the incoming data events quickly enough. > The problem is that the data analysis needs to happen as fast as > possible. However if the timer period is equal to or less than the > execution time of the OnTimer() function, there is no idle time and > OnIdle() never gets called. Yes. > This means my toolbars don't update and > messageboxes take a very long time to appear. Actually, these problems are more closely related to your saturation of the message pump. If all your application does is porcess WM_TIMER messages, you'll find that no other messages of _any_ sort get time to run, and that means that they're way behind in the queue. In Win32, you can't overflow the queue so you probably won't actually crash--you'll just notice sluggish user-interface response. You might consider using a spearate thread to do your data acquisition. You can adjust the thread priority up a bit and make sure you get enough cycles. > I added the folowing code in hopes of solving the lack of idle time > processing, unfortunately it causes an exception if a toolbar is > moved. Is there any reason this should not work? > The OnIdle Call; You don't point out where, exactly, you've coded this. > The Error Message; > > 'CDC:DrawDragRect(const tgaRect * 0x0066f678 unhandled exception in > Build.exe (MFC40D.DLL) 0x00000005: Access violation ' But, apparently, you're doing it at a point where your application has, or where, on your application's behalf, MFC has created and plans to use a temporary object. Since you call OnIdle(), the temporary object goes away and then is referenced and you crash. If the call to OnIdle() is in response to the WM_TIMER messages, you'll certainly crash during almost any user interaction with your application. (Your subject implies that this is where you're calling OnIdle(), but your message doesn't say anything speicifc about it.) > The function call that caused the exception, from the debugger; > > CDC::DrawDragRect( > const tagRECT * 0x0066f678 {top=33 bottom=62 left=19 right=439}, > tagSIZE {...}, > const tagRECT * 0x00681a3c {top=33 bottom=62 left=16 right=436}, > tagSIZE {...}, > CBrush * 0x00683310 {CGdiObject}, > CBrush * 0x00683310 {CGdiObject}) line 203 If you're so busy with data collection, why are you doing all of this painting? A tracking rect uses a lot of CPU. Or are you doing this in response to the user while the acquisition is concurrently happening? Anyway, it sounds like the data collection stuff is a prime candidate for a worker thread. .B ekiM http://www.nwlink.com/~mikeblas/ Why does the "new" Corvette look like a 1993 RX-7? These words are my own. I do not speak on behalf of Microsoft.
| Вернуться в корень Архива |