Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C

Message Thread Using IoCompletionPort

3.11/5 (6 votes)
1 May 2008CPOL1 min read 2   320  
Thread communication made easy!

Introduction

Windows has a simplified built-in mechanism for communication among threads, using message loops. APIs such as GetMessage(), PeekMessage() can be used to achieve this. E.g.,

C++
MSG msg;
PeekMessage(
    &msg,
    NULL,
    0,
    0,
    PM_NOREMOVE);
while (true)
{
    BOOL bRet = GetMessage(
            &msg,
            NULL,
            0,
            0);
}

Once the loop is setup, use PostThreadMessage() to send the message across. E.g.,

C++
PostThreadMessage(
    nThreadId,
    nMsg,
    wParam,
    lParam);

In fact, message based communication is the building block of Windows. Of course, it has serious security implications as the source of the message is not known to the receiver, but that's a topic for another article.

In this article, I used this concept and the MFC macro style message handler declaration and wrapped them in a class that lets you send messages in two different modes:

  • PostMessage
  • SendMessage with timeout

The Code

In order to construct the message loop, I used CreateIoCompletionPort(), GetQueuedCompletionStatus() instead of the above mentioned method. The reasons for this are as follows:

  • IoCompletionPorts are fast and less resource intensive.
  • No restriction as in the other methods where the thread needs to belong to the same desktop, etc.

OK, let's see an example. By the way, the attached files have a Visual Studio based project that you can compile and run. Check the DemoThread class.

First, derive a class from MsgThread:

C++
// DemoThread.h
class DemoThread : public MsgThread
{
    DECLARE_MSG_MAP();
private:
    void OnMsgGoGetPizza(
        WPARAM wParam,
        LPARAM lParam);
};
// DemoThread.cpp
BEGIN_MSG_MAP(DemoThread, MsgThread)
    ON_MSG(kMsgGoGetPizza, OnMsgGoGetPizza ) 
END_MSG_MAP()
void
DemoThread::OnMsgGoGetPizza
(
    WPARAM wParam,
    LPARAM lParam
)
{
}

Elsewhere in your code:

C++
DemoThread rThread1;
rThread1.Start();
rThread1.PostMessage(
    kMsgGoGetPizza,
    (WPARAM) 5,
    0);
rThread1.Stop();

And that's it. Just be careful; if you use SendMessage, you might end up in a deadlock if you haven't designed things properly.

Just include MsgHandler.[h,cpp] and MsgThread.[h,cpp] in your project. I hope you find it useful. Any comments or suggestions are most welcome.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)