Board index » cppbuilder » How to keep a console app busy and responsive?

How to keep a console app busy and responsive?


2007-02-07 11:55:54 PM
cppbuilder74
Hello out there,
a console mode app of mine needs to periodically perform some action
while still being able to react to input from the user.
I thought that the combination of getting the handle to the input
console and then doing a WaitForSingleObject with a suitable timeout
would accomplish what I need - but it doesn't work.
The program below (when started from a console)
1) repeatedly prints out the message "No key ...." UNTIL any key is
pressed, at which point
2) it ALWAYS goes into the 'ReadConsole' after the WaitForSingleObject
call, whether a key is pressed or not. Of course it blocks there if no
key is pressed - the message "No key ..." is never again seen.
When started via Start | Run, step (1) from above is skipped.
Any help to get me on the right track will be greatly appreciated,
Best regards
Helmut Giese
-----
#include <windows.h>
#include <stdio.h>
#pragma argsused
int main(int argc, char* argv[])
{
HANDLE inHdl, outHdl;
char inBuff[80];
int done = 0;
DWORD cnt, dwRes;
// get console handle
inHdl = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(inHdl, 0);
// SetConsoleMode(inHdl, ENABLE_PROCESSED_INPUT);
printf("Trying to be busy & responsive in console mode\n");
while ( !done ) {
dwRes = WaitForSingleObject(inHdl, 1000);
if ( dwRes == WAIT_OBJECT_0 ) {
// input available
ReadConsole(inHdl, inBuff, 1, &cnt, 0);
switch ( inBuff[0] ) {
case '1': printf("Received key '1'\n"); break;
case '2': printf("Received key '2'\n"); break;
case 'q': done = 1; break;
}
} else {
printf("No key - going to do other work\n");
}
}
return 0;
}
-----
 
 

Re:How to keep a console app busy and responsive?

Helmut Giese wrote:
Quote
a console mode app of mine needs to periodically perform some action
while still being able to react to input from the user.
I thought that the combination of getting the handle to the input
console and then doing a WaitForSingleObject with a suitable timeout
would accomplish what I need - but it doesn't work.
Have you tried ResetEvent( inHdl ) ?
Maybe FlushConsoleInputBuffer( inHdl ) ?
The docs for ReadConsole don't mention waiting, but the docs for
ReadConsoleInput do. You might try that function.
My own code uses polling with a Sleep( 10 ) because I also check for
UDP messages. Several copies of the program can run with no
notiiceable delays.
I also allow mouse clicks which brings in mouse movements as well
(which I ignore).
GetNumberOfConsoleInputEvents( stdin, &written );
if( 0 == written )
{ ++WaitCounter;
if( WaitCounter>100 )
{ WaitCounter = 0;
BackgroundProcess();
}else{
Sleep( 10 );
};
}else{
ReadConsoleInput( stdin, &input_record, 1, &written );
// if you want background to only fire after
// 1 second of inactivity
WaitCounter = 0;
};
See Reading Input Buffer Events
msdn2.microsoft.com/en-us/library/ms685035.aspx
- - - -
In any case, the usual method these days is to use threads.
Main() could create a CancelEvent, then start the background thread.
When main() wants to exit, it signals CancelEvent to terminate the
background thread.
Main() could also set a global boolean whenever it processes a
keystroke.
The background thread could WaitForSingleObject on the CancelEvent,
and process during WAIT_TIMEOUT, exiting on WAIT_OBJECT_0.
while( 1 )
{ if( WAIT_OBJECT_0 == WaitForSingleObject( CancelEvent, 1000) )
break;
if( GlobalKeyPressed )
{ // key was pressed while we slept
GlobalKeyPressed = false;
}else{
BackgroundProcess();
};
};
This has the advantage of being responsive even when the background
thread is busy.
Whichever thread method you use, you would also want to add
SetConsoleCtrlHandler( &CtrlHandler, TRUE);
to catch the Big Red X and other app closers so you can signal the
thread to exit nicely.
 

Re:How to keep a console app busy and responsive?

Hi Bob,
many thanks for the info - lots of ways to chose from.
- Calling FlushConsoleInputBuffer did not change anything
- going the multi-threaded way looks a bit like too much effort for
this particular app,
- so I think I use your polling example
Oh, and thanks for the link to Input Buffer Events.
Best regards
Helmut Giese
 

{smallsort}

Re:How to keep a console app busy and responsive?

in addition..
while (!dgDone)
{
// standard console processing
//
INPUT_RECORD lpPeekBuffer = { '\0' };
DWORD dwNumEventsPeek = 0;
::PeekConsoleInput(inHdl, // handle to a console
input buffer
&lpPeekBuffer, // pointer to the
buffer for peek data
sizeof(INPUT_RECORD), // number of records to
read
&dwNumEventsPeek); // pointer to number of
records read
if(dwNumEventsPeek)
{
read the console .. it has events.
}
do something else
repeat..
}
"Helmut Giese" < XXXX@XXXXX.COM >wrote in message
Quote
Hi Bob,
many thanks for the info - lots of ways to chose from.
- Calling FlushConsoleInputBuffer did not change anything
- going the multi-threaded way looks a bit like too much effort for
this particular app,
- so I think I use your polling example

Oh, and thanks for the link to Input Buffer Events.
Best regards
Helmut Giese