|
Hi Kumar,
I have some query related to multithreading,
here
for ( ; LoopCounter < NUM_THREADS ; LoopCounter )
{
hThrd [ LoopCounter ] = CreateThread ( NULL , 0 ,
(LPTHREAD_START_ROUTINE)ThrdFunc ,
(LPVOID)LoopCounter , 0, &Id [ LoopCounter ] );
if ( !hThrd )
{
cout<<"Error Creating Threads,,,,.exiting"<<endl;
return -1;
}
Sleep ( 100 );
}
here creating number of threads using foor loop and multiple thread handles get created.but if the each thread suppose to perform different work ,
For Example
one thread can write the data into database and another thred read the data from database.
How this will perform,
Please explain...
|
|
|
|
|
Please use different messages for different threads to achieve this.
|
|
|
|
|
|
I was not aware that GetMessage can be used in a non Window application or an application where no Window Message loop. This is entirely new thing to me. Thanks for the article.
|
|
|
|
|
Thanks for such a nice explanation.
its much helpful for starters.
|
|
|
|
|
i Start to love Multithreading because of this aritcle.
Thanks & regards
Muthulakshmanan
muthu
|
|
|
|
|
5 stars from me...
Just wondering if you could email me an example / source of a WIN32 multithreaded DLL that can callback to a client gui to update it from worker threads..
Cheers
Luois
|
|
|
|
|
Can we increase or decrease the size of Message Queue?
|
|
|
|
|
In MSDN, reference PostThreadMessage, you can find these:
Windows 2000/XP
HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
Windows NT
CurrentVersion
Windows
USERPostMessageLimit
The minimum acceptable value is 4000.
But I shouldn't try whether it is correct.
I like programming.........
|
|
|
|
|
Hi auther nice article
I am trying to send my own message and parse it from within my console application in vc++ . But its not work ing .. my code is below
UINT CONN = RegisterWindowMessage(TEXT("CONNECT"));
HWND GetConsoleHWND();
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
....
CreateThread(NULL, 0, MessageLoop, NULL, 0, NULL);
.....
}
unsigned long __stdcall MessageLoop(void *a_pArg)
{
MSG Msg;
while(GetMessage(&Msg, GetConsoleHWND(), 0, 0))
{
printf("Msg.message:%u\n", Msg.message);
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
printf("Returning");
return -1;
}
HWND GetConsoleHWND()
{
char title[256] = "";
char className[20] = "";
// Get the name of this executable.
GetModuleFileName(0, title, sizeof(title));
// See if we're running on Win95 or NT.
OSVERSIONINFO info;
info.dwOSVersionInfoSize = sizeof(info);
GetVersionEx(&info);
int platform = info.dwPlatformId;
// If NT then the class name is 'ConsoleWindowClass'
// The title is the entire path and filename.
if (platform == VER_PLATFORM_WIN32_NT)
strcpy(className, "ConsoleWindowClass");
// Return the result of FindWindow().
return FindWindow(className, title);
}
Now from another thread within the application I am posting my message like this ...
PostMessage(GetConsoleHWND(),CONN,0,0);
But the GetMessage(&msg...) is not firing . why ? Is there anything else needed ..?
regds
Dharani babu S
|
|
|
|
|
How to create message queue? I haven't found any code to creat message queue before inovking GetMessage API in the thread function ? when and how the message queue was created ?
Thanks a lot!
|
|
|
|
|
Message queue is usally created when the thread is created, well not exactly when the thread is created. It is created by the OS whenever the thread needs a message queue like when postmessage,getmessage,postthreadmessage etc is called.
So we dont explicitly create the message queue
|
|
|
|
|
Mr.Prakash wrote:
It is created by the OS whenever the thread needs a message queue like when postmessage,getmessage,postthreadmessage etc is called
Not quite correct -- a thread's message queue is automatically created by the OS after the first attempt to read a message, i.e. upon the first time GetMessage or PeekMessage gets called. In other words, you can PostThreadMessage s all day long -- if the thread doesn't care to read them, each call to PostThreadMessage fails. Read my other post further down to see how you can exploit this behaviour to check whether a thread has finished reading startup data, for example.
If your thread creates a window, though, the OS creates a message queue regardless of any message loop, although it certainly wouldn't be wise not to supply one.
.f
|
|
|
|
|
Thank you.
Which book did u get this from?
|
|
|
|
|
My main resource for this sort of internal information is Jeffrey Richter's Advanced Windows which is now known as Programming Applications for Microsoft Windows[^]. The MSDN is also a good source of information, but doesn't go into that much detail. In fact, I haven't been able to find specific details on the creation of message queues, other than occasional hints.
Maybe it's a good idea to tell you the entire story behind threads and message queues: For performance reasons every thread that is created in Windows is assumed to be a worker thread. As a consequence, the system keeps it Lean And Mean (tm) and doesn't allocate all those structures that are needed by user interface threads. The first time, though, a thread calls a user interface or GDI API function, it is turned into a fully fledged UI thread, including the creation of a message queue.
Since CreateWindow[Ex] is a user interface function, any thread that creates a window therefore also has a message queue. Now you might say, that PostThreadMessage is also a user interface function. That's true, but since it isn't called from inside the thread, it just won't create a message queue for the thread you intended to send a message to.
This is a Good Thing (tm), too, since your thread 'knows' what it needs and is guarded against client code from outside telling it what it should have, in this case a message queue.
I hope this makes sense,
.f
|
|
|
|
|
According to MSDN, the OS create a message queue when you call a GDI/USER function the very first time
|
|
|
|
|
Hi.
I've been using this idea just recently, and to make my message queue happen, i have had the following code. However. Sometimes the queue just won't appear!!!! DAMN IT!!! Does anyone know why? And how i can FORCE windows to make the queue? It is getting very frustrating, and i can't release software with a unreliably created message queue!!!
Thanks for any helps or pointers...
MSG msg;<br />
memset((void*)&msg, 0, sizeof(MSG));<br />
<br />
<br />
while (!PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE))<br />
{<br />
PostThreadMessage( GetThreadID(), WM_DISPATCH_THREAD_MESSAGE_WAKEUP, 0, 0 );<br />
Sleep(100);<br />
}
|
|
|
|
|
You can use the following method that the WTL had used in its MSDI app:
MSG msg;
// force message queue to be created
::PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
|
|
|
|
uhmmmm...... yeah. That's what i'm already doing.
If you have a look at my post, I already use PeekMessage (as the condition of the while loop), and it is repeatedly called until it succeeds.
And just in case you are wondering that i don't use the arguments WM_USER in my call to PeekMessage, ... it is because i am not bothering with any message filtering.
Yes, so, in otherwords, yep... already doing that. It DOES work sometimes... and then others it doesn't. Seemingly intermittant. Worse still, it seems to work more often if i am watching it!! (i.e. debugging the damn app)
excerpt from msdn
------------------
If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns all available messages (that is, no range filtering is performed).
|
|
|
|
|
When I need to wait for a particular thread that needs a message queue anyway I would usually do it like this:
hThread = BeginThread( ..., &ThreadId );
while( !PostThreadMessage( ThreadId, WM_NULL, 0, 0 ) )
Sleep( 0 ); and in the thread function:
GetMessage( &msg, NULL, WM_NULL, WM_NULL );
Since the thread won't have a message queue, until the first call to GetMessage , the PostThreadMessage API call fails -- once it succeeds, we know that the respective thread has stored the information passed via the lpThreadParm and the main thread is safe to continue. As long as the amount of time spent before calling GetMessage is not too long, this should work fine. At least you won't have to Sleep an arbitrary amount of time. In addition, your code doesn't check for failure of the PostThreadMessage call, but simply relies on n seconds being enough time for the thread to have started and created it's message queue.
One more piece of related information: If you intend to use CRT functions inside any of your thread functions you should call _beginthreadex instead of CreateThread -- otherwise you will get memory leaks due to the multithreaded CRT implementation not getting a chance to clean up the multithreading-relevant structures it allocated.
.f
p.s.: Your final call to WaitForMultipleObjects specifies an INFINITE timeout value. There is a potential problem with that, since it would make the entire application stop responding if a single thread hangs. I would rather specify a finite timeout value and if it's reached, call TerminateThread for those threads that haven't terminated already.
|
|
|
|
|
Its a good idea but i dont know wheather there is a "flaw"
To you use messagequeue for syncronization according to me is a bad idea.
When thread is created, message queue is not created it is created when a message is read from the queue, fine but dont ya think now its consuming more memory.???
Instead a simple event will do the same with less memory consumption.
I feel that if the thread is a worker thread then this idea is not acceptable.
But its a very good idea for ui thread.
|
|
|
|
|
The most important thing to note is: this is not meant to replace synchronization via kernel objects, but rather an alternative way of achieving a similar result. Consequently, the intention was not to present a one-size-fits-all solution.
Although you are correct that memory usage will be higher when installing a message queue, it is generally not a real world problem to be concerned about. I'm currently also developing software for mobile devices (8MB RAM, no virtual memory via swap files, several applications installed in RAM already) where running out of memory is a very real problem that has to be dealt with. For current desktop PC's allocation of a few extra KB is usually nothing to pull your hair about.
It is extremely important to be very clear about the pros and cons of both approaches (synchronization with kernel objects vs. message passing), and how they match up with your individual requirements. The most obvious advantage of kernel object synchronization is, that they are very efficient, both with respect to memory footprint and execution time. However, using events, it is tiresome to control a specific thread: If you put a kernel object in signaled state, any thread waiting for this object is potentially eligable to continue execution.
If you are in a situation where you need to have this sort of control, message passing may be the way to go, as it gives you the opportunity to communicate with a specific thread. Simulating this behaviour with kernel objects would force you to create one for each thread that you need to control individually. Doing the same thing with message passing is probably easier to do, less trouble to maintain, and easier to follow for your fellow programmers that may have to work with your code in the future.
To sum it up: the code provided in this article (and it's discussion) offer alternatives, without claiming to be the one-and-only solution. With programming there is usually more than one way to achieve any given task. It's up to the software developer to choose wisely, which option to go with in any given scenario.
Hopefully, this fills in the gaps that may have remained unanswered and puts the topic back into perspective.
Regards,
.f
|
|
|
|
|
Looking at your code, I see you have some 'Sleep(100)' statements within the three for-loops. What are the reasons for those?
I understand the 10 seconds sleep after the thread-creations - though I would personally (in a production environment) use another form of "synchronization" (possibly using events and a WaitForMultiple*), to know whether or not all the threads are ready to receive work. Of cause this would be beyond the scope of your article I presume, though you might want to add a comment to that statement, that it is a "very crude" way to ensure that the (worker-)threads will be up-and-running.
BTW you have a flaw in the "// Wait for all threads to exit" WaitFor* statement. What happens if I change the macro "NUM_THREADS" to, lets say 1? Or 8? Anything but 2.
|
|
|
|
|
Hi,
Small but good article.
Have you already made some tests to compare the performance of the two approaches? I suspect the events to be faster than the messages, but I might be wrong.
Regards
Marc Wohlers
|
|
|
|
|
Hi Marc, As far as the performance is concerned, creating a message queue for each thread will certainly degrade the performance as compared to single event which can be used to signal multiple threads. i.e PulseEvent API. its up to you and requirements of your application to decide. I have used Message queue in my applications, having not more than 10 threads. Each thread can trigger multiple functionality. I found Message Queue based solution is pretty easy as companed to event + variables. As far as 10 threads are concerned I haven't seen any visible difference in performance.
Regards,
Deepak
|
|
|
|
|