# VC++ multi-thead Input problem

This topic is 4501 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm trying to run a thread on the background of my window program. I'm using VC++ 6.0 API (not MFC). What I'm trying to do is to create a thead that respond to WM_KEYDOWN message, so the main WndProc doesn't have to waste time doing so. And the program can archieve some concurrency. However, the thread doesn't seem to respond to those A, B, C, D, 1, 2, 3, num_0, num_1 ....keys; yet it works ok to the to F1, F2, up arrow, down arrow... keys. I have to put the WM_CHAR message on in order for the thead respond to a, b, c, d, 1, 2... keys. But if I do so the value on the WParam is different. For example, the numpad keys 0, 1, 2, 3... will be the same as 0, 1, 2, 3... which is different on MS Virtual Keys. I've no idea why the thead doesn't repsond to the WM_KEYDOWN for those keys, but others are ok. While I must put the WM_CHAR message on. Thank you.

##### Share on other sites
How is your message loop set up? Do you have a message loop in the secondary thread as well as your main thread, or just a single loop in the main thread that requeues/reposts messages over to the other thread?

##### Share on other sites
Well here is the code, thanks for help

DWORD WINAPI input_determine2 ( PVOID p_void )
{

PMSG p_msg = ( PMSG ) p_void ;

int temp = false ;

char test_str [50] = "" ;

while ( p_msg->message != WM_QUIT )
{

switch ( p_msg->message )
{

case WM_KEYDOWN:
case WM_CHAR: // MUST have this messsage otherwise the thread
// WILL NOT capture each input

temp = ( int ) p_msg->wParam ;
sprintf ( test_str, "%X", temp ) ;
MessageBox ( NULL, test_str, "Key Down", MB_OK ) ;

break ;

default:

break ;

}

}

return ( DWORD ) true ;

}

##### Share on other sites
Quote:
 I've no idea why the thead doesn't repsond to the WM_KEYDOWN for those keys, but others are ok. While I must put the WM_CHAR message on.

Your problem doesn't seem to deal with threading, but character codes. See if this solves your problem.

##### Share on other sites
How are you splitting the thread? How and when does input_determine2 get called?

##### Share on other sites
splitting the thead? I just use the CreateThread function to create the thread at the beginning of the program. And the thread never gets call - because it's a thread. It runs on the background until it sees the WM_QUIT message on the main program's message queue.

I guess the problem is that the main program process the WM_KEYDOWN message and remove it on it's message queue, but not yet process the WM_CHAR. That's what I guess why the thread doesn't see the WM_KEYDOWN, but WM_CHAR message. I probably need to use the PeekMessage instead of GetMessage function.

Any idea how to tell the OS not to remove the message?

Thanks,

##### Share on other sites
Sorry, I don't think you understood my question.

What is the entry point function you specify when you split (create) the thread? What does the thread's execution loop look like? How and when do you call the input_determine2() function?

I don't know for sure because I don't have a clear idea of how your code is structured, but it sounds to me like you're expecting to have a message pump in a separate thread that handles messages out of the main application message queue. This is not a good idea, and can cause some horrible synchronization bugs.

##### Share on other sites
Ok, I think I know why. And I kinda sorta the first half of it. Yes, it's having the synchronization problem. The first half was the main messge processed the WM_KEYDOWN message, but the thread doesn't; yet the thead saw the WM_CHAR which has not be processed by the main application (because it comes after it).

Now, I put the main to wait for the thread to see the WM_KEYDOWN message. However, the thread comes back after that, but the main application has not yet removed the message, so sometimes the thread sees the same message twice in a row. I'm now trying to reslove this problem!

I know using mutex or something like is the best way to synchronizate the problem. But I'm try to be use "the most less expensive" way.

I'm trying to find out how to use the thread to remove the message it has seen already.

Ok, my main loop

int execute (void){	input_tracker_thread = CreateThread (	NULL, 0, input_determine2,											&main_frame_handler.application_message,											false, &thread_id_input ) ;	while ( GetMessage ( &main_frame_handler.application_message, NULL, 0, 0 ) )	{		TranslateMessage ( &main_frame_handler.application_message ) ;		DispatchMessage ( &main_frame_handler.application_message ) ;	}	ResumeThread ( input_tracker_thread ) ;	WaitForSingleObject ( input_tracker_thread, INFINITE ) ;	return main_frame_handler.application_message.wParam ;}

and my Windown procedure is

LRESULT CALLBACK app_proc_callback ( HWND h_wnd, UINT u_msg, WPARAM w_par, LPARAM l_par ){	HDC				hdc ;	RECT			rt ;	PAINTSTRUCT		ps ;	switch ( u_msg )	{	case WM_CHAR:					// MUST have this messsage otherwise the thread									// WILL NOT capture each input	case WM_LBUTTONDOWN:	case WM_LBUTTONUP:	case WM_MBUTTONDOWN:	case WM_MBUTTONUP:	case WM_RBUTTONDOWN:	case WM_RBUTTONUP:	case WM_SYSKEYDOWN:	case WM_SYSKEYUP:	case WM_KEYDOWN:	case WM_KEYUP:		MsgWaitForMultipleObjectsEx ( 1, &input_tracker_thread, 10, QS_KEY | QS_MOUSEBUTTON, 0 ) ;		return 0;	case WM_PAINT:		hdc = BeginPaint ( h_wnd, &ps ) ;		// TODO: Add any drawing code here...		GetClientRect ( h_wnd, &rt ) ;		DrawText ( hdc, "This is Main Frame Hello World", -1, &rt, DT_CENTER | DT_VCENTER | DT_SINGLELINE ) ;		EndPaint ( h_wnd, &ps ) ;		return 0 ;	case WM_DESTROY:		PostQuitMessage(0) ;		return 0 ;	}	return DefWindowProc ( h_wnd, u_msg, w_par, l_par ) ;}

And the thread function is

DWORD WINAPI input_determine2 ( PVOID p_void ){	PMSG p_msg = ( PMSG ) p_void ;	int temp = false ;	char test_str [50] = "" ;	while ( p_msg->message != WM_QUIT )	{		switch ( p_msg->message )		{		case WM_SYSKEYDOWN:		case WM_KEYDOWN://		case WM_CHAR:				// MUST have this messsage otherwise the thread									// WILL NOT capture each input			temp = ( int ) p_msg->wParam ;			sprintf ( test_str, "%X", temp ) ;			MessageBox ( NULL, test_str, "Key Down", MB_OK ) ;			break ;		default:			break ;		}	}	return ( DWORD ) true ;}

##### Share on other sites
Unfortunately, threads are not something you can do halfway. You either need to do a specific and complete synrchonization model, or stick to single-threading; any compromises will lead to nothing but a lot of hacks and very hard-to-find bugs. Threads are like hand grenades: if you use them well, and properly, you can get very effective results; misuse them, or use them sloppily, and you'll be missing a few body parts - if you're still alive.

Out of curiosity, why would your program need to be handling user input in a separate thread? In most cases, user input will affect such a huge portion of your program that trying to handle it in a separate thread from everything else is a recipe for a lot of headaches. If you really genuinely need to process input asynchronously, I'm afraid the only way to do it well is to do it fully and build in a synchronization system with the rest of your program. Even if you can get a half-baked model to work for a while, I'll guarantee that it will fail eventually - and it will probably be a pretty spectacular failure when it goes.

Anyways, I don't mean to be excessively morbid or put you off threading - just be aware of what you're dealing with and the dangers of not taking proper precautions [smile]

##### Share on other sites
Yeah, I understand the issue.

Now, I'm KINDA solve that problem using "SuspendThread" at the end of each loop. Also, "ResumeThread" and "MsgWaitForMultipleObjectsEx" to archieve the classic of Sleep and Awake technique.

Well, it's work ok for now. I'll post again if I have problem again.

##### Share on other sites
Why not fix it propertly now so you don't have 10,000 lines of code to fix later? Oh well some people like pain.

Anyways, anyone have any good links to learning threading/syncing? I did a few google searches a few months ago and came up with some pretty lame (read NT4 articles) results.

Thanks.

try this webpage

##### Share on other sites
Thanks looks good :)