Click here to Skip to main content
Click here to Skip to main content

Using WIN32 Message Queue in C++ / WIN32 Multithreaded Applications

, 24 Feb 2004
Rate this:
Please Sign up or sign in to vote.
How to use WIN32 Message Queues in MultiThreaded Environments instead of kernel objects.

Introduction and Motivations

I am not a great lover of Multithreaded applications development, but at the end I come up with writing more multithreaded applications than single threaded ones. Though they are little bit difficult to manage, sometimes they provide us unique opportunity to solve a particular problem, provided your application is not CPU intensive. if your application is CPU intensive then multithreading will not give you its stated performance.

Every application is having its own thread creation policies for example

  • Application may create a thread pool and waits for the requests to be serviced.
  • Application may create thread on the fly when it needs to service some request.

In case 1 you need to have some mechanism to make a thread wait for some kind of signal. The signal may be generated in case when you need the service of any particular thread.

Using WIN32 Kernel Objects

WIN32 provides kernel objects like WIN32 Events to handle this kind of situations. you can use one of the WaitFor.. APIs to wait for a particular event inside a thread. The idea behind waiting for kernel objects is that it won't eats up all of the available CPU while waiting, otherwise you could have busy wait. Look at the following code.

#include <windows.h>
#include <iostream>

using namespace std;

HANDLE        hEvent;

DWORD    WINAPI ThrdFunc ( LPVOID n )
{
    int        TNumber    =    (int) n;
    WaitForSingleObject ( hEvent , INFINITE );
    cout<<"Event gets signaled...."<<endl;
    return 0;
}

int    main()
{
    HANDLE        hThrd;
    DWORD        Id;
    //    Create a Event
    hEvent    =    CreateEvent ( NULL , false , false , "Event 10234" );

    hThrd    =    CreateThread ( NULL , 0 , 
       (LPTHREAD_START_ROUTINE)ThrdFunc ,
       (LPVOID)0 , 0 , &Id );
    if ( !hThrd )
    {
        cout<<"Error Creating Thread ..."<<endl;
        return -1;
    }
    //    Wait For some time before giving out any signal
    Sleep ( 2000 );
    SetEvent ( hEvent );
    //    Wait for the thread to gets killed
    WaitForSingleObject ( hThrd , INFINITE );
    //    Close the handler
    CloseHandle ( hEvent );
    CloseHandle ( hThrd );
    return 0;
}

The code above shows that a thread is being created and it is waiting for an auto reset event. The event is signaled by the main thread after 2 seconds. once the waiting thread gets the signal it continues its execution and exit. You can achieve the same functionality using WIN32 Message queues.

Using WIN32 Message Queues

WIN32 message queues have certain advantages as compared to event based mechanism. As we will see you can send different messages to a single thread. The following code uses PostThreadMessage WIN32 API to post specific message to a particular thread.

Advantage Message Queue over Events

  • You are sure that you are posting message to which thread, while in the case of events you can't guarantee which thread will get released if more than one threads are waiting on same event.
  • You can send a range of user defined messages to a thread, if you want the thread to behave differently. However in case of events you can just signal the events, no other information can be given.

Using Message queue in Multithreaded application

Message queues can be created even in console applications. you don't need a windows handle for it. Message queues are created in WIN32 console application as soon as you call message extractor functions like GetMessage and PeekMessage.

In my code below I have used GetMessage. PeekMessage is commented. The only harm in using PeekMessage is that PeekMessage doesn't waits for the message to come into the queue and will eats up all the available CPU which is undesirable in many cases. Here is the code

//    User Defines Messages
#define        THRD_MESSAGE_SOMEWORK        WM_USER + 1
#define        THRD_MESSAGE_EXIT            WM_USER + 2
//    Application Specific Preprocessor definitions
#define        NUM_THREADS                    2

DWORD WINAPI    ThrdFunc ( LPVOID n )
{
    int    TNumber    =    ( int )n;
    //    Here we will wait for the messages
    while ( 1 )
    {
        MSG    msg;
        //BOOL    MsgReturn  =  PeekMessage ( &msg , NULL , 
        //    THRD_MESSAGE_SOMEWORK , THRD_MESSAGE_EXIT , PM_REMOVE );
        BOOL    MsgReturn    =    GetMessage ( &msg , NULL , 
            THRD_MESSAGE_SOMEWORK , THRD_MESSAGE_EXIT );
            
        if ( MsgReturn )
        {
            switch ( msg.message )
            {
            case THRD_MESSAGE_SOMEWORK:
                cout<<"Working Message.... for Thread Number "
                   <<TNumber<<endl;
                break;
            case THRD_MESSAGE_EXIT:
                cout<<"Exiting Message... for Thread Number "
                   <<TNumber<<endl;
                return 0;
            }
        }
    }
    
    return 0;
}

int main()
{
    HANDLE    hThrd [ NUM_THREADS ];
    DWORD    Id [ NUM_THREADS ];
    short LoopCounter = 0;
    //    Create all the threads
    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 );
    }
    Sleep ( 10000 );
    //    Send Working Message to all Threads 
    for ( LoopCounter = 0; LoopCounter < NUM_THREADS ; LoopCounter ++ )
    {
        PostThreadMessage ( Id [ LoopCounter ] , 
            THRD_MESSAGE_SOMEWORK , 0 , 0 );
        Sleep ( 100 );
    }
    //    Sleep againg for 1 seconds and send exit message to all threads
    Sleep ( 1000 );
    for ( LoopCounter = 0; LoopCounter < NUM_THREADS ; LoopCounter ++ )
    {
        PostThreadMessage ( Id [ LoopCounter ] , THRD_MESSAGE_EXIT, 0 , 0 );
        Sleep ( 100 );
    }
    //    Wait for all threads to exit
    WaitForMultipleObjects ( NUM_THREADS, hThrd , true , INFINITE );
    //    Close All handles
    for ( LoopCounter = 0; LoopCounter < NUM_THREADS ; LoopCounter ++ )
        CloseHandler ( hThrd [ LoopCounter ] );

    return 0;
}

In the code above we created two user defined messages. Each thread waits for the particular message. The message is send to all threads from the main thread. The main thread waits for all threads to exit before exiting itself.

History

  • Last updated on Feb 26, 2004

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Deepak Kumar Gupta
Architect
India India
I love programming and started (in 1995)even before I got some professional education on the same. Since then I've worked on IP network stack (written IPv6 stack and next generation TCP Stack), VoIP, IP Security (IKE / IPSec).
My preferred programming language is C++ and I always explore the ways to improve the A.I based systems using enhanced algorithms and data structures.

Comments and Discussions

 
GeneralMy vote of 2 Pinmemberranjithkumar8120-Dec-12 19:47 
GeneralRe: My vote of 2 PinmemberDeepak Kumar Gupta18-Jun-13 18:34 
GeneralMy vote of 5 Pinmemberranjithkumar8120-Dec-12 19:41 
QuestionThanks Pinmemberpkv99024-Mar-12 17:33 
GeneralNice Aritical Pinmembergauravagarwal.cs@gmail.com13-Sep-07 2:14 
GeneralVery nice Aritical Pinmembermuthulakshmanan7-Dec-06 19:17 
GeneralMulti-threaded DLL PinmemberJRaiden30-Jan-06 1:27 
GeneralMessage Queue Size PinmemberRavi Ranjan18-Jul-05 18:29 
GeneralRe: Message Queue Size PinmemberAson19-Jan-09 19:58 
GeneralUser defined Message handling Pinmemberdharani6-Sep-04 3:00 
QuestionWhen the thread created its mesage queue ? PinmemberTom_lyd1-Mar-04 19:30 
AnswerRe: When the thread created its mesage queue ? PinmemberMr.Prakash1-Mar-04 19:46 
GeneralRe: When the thread created its mesage queue ? Pinmember.:fl0yd:.3-Mar-04 8:05 
GeneralRe: When the thread created its mesage queue ? PinmemberMr.Prakash3-Mar-04 13:13 
GeneralRe: When the thread created its mesage queue ? Pinmember.:fl0yd:.4-Mar-04 3:15 
GeneralRe: When the thread created its mesage queue ? PinmemberDandy Cheung4-Mar-04 23:18 
GeneralRe: When the thread created its mesage queue ? Pinmemberwinsute23-Mar-05 18:48 
GeneralRe: When the thread created its mesage queue ? PinmemberDandy Cheung23-Mar-05 19:21 
GeneralRe: When the thread created its mesage queue ? Pinmemberwinsute23-Mar-05 19:53 
GeneralMore solid thread synchronization Pinmember.:fl0yd:.25-Feb-04 6:36 
GeneralRe: More solid thread synchronization PinmemberMr.Prakash3-Mar-04 13:20 
GeneralRe: More solid thread synchronization Pinmember.:fl0yd:.4-Mar-04 3:59 
GeneralReasons for Sleep(100) PinmemberDeckerDK24-Feb-04 21:50 
GeneralPerformance PinsussMarc Wohlers20-Feb-04 1:46 
GeneralRe: Performance PinmemberDeepak Kumar Gupta20-Feb-04 17:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 25 Feb 2004
Article Copyright 2004 by Deepak Kumar Gupta
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid