15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


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 Razzetti  at 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.





| Вернуться в корень Архива |