Can Send message properly, but can't receive them in winapi

This is a code designed to roughly estimate the time it takes from the moment of asking the Windows OS to queue a message into a window’s queue, till the window’s thread is actually given CPU time. The receiving thread has its Message-Only window to receive and process messages. The message are sent via a separate thread.

The code compiles perfectly, and the message sending function returns non-error, but the message won’t be received. I won’t need to add all the code that initializes and terminates the threads as they are already tested to be working perfectly.

Also, the receiving window does receive OS messages perfectly fine. So the problem is only in not receiving the custom messages.

#define INTER_MESSAGE (WM_USER + 1)
FCriticalSection ThreadsMutexes_A;//UE-style mutex.

struct InterThreadMessagingReportStruct
    {
        bool MessageEverReceived = false;//To check if message received even once.
        
        int Count = 0;
        double Average = 0.0;
        double min = HUGE_VAL;
        double max = -HUGE_VAL;
        void Update(double vlu)
        {
            //Averaging:
            Average = (Average * (double)Count + vlu) / (double)(Count + 1);
            //Updating count.
            Count++;
            //Updating min and max.
            if (vlu < min)min = vlu;
            if (vlu > max)max = vlu;
        }
    };
InterThreadMessagingReportStruct* InterThreadMessagingReportObject = new InterThreadMessagingReportStruct();
    
//This is the ThreadFunction of the sending thread.
DWORD WINAPI SendingThreadFunc(LPVOID lpParam)
{
    while(true)
    {
        DWORD dwTargetThreadID = ISProt0::MainRAM_ThreadsHandlingObject->pData_A->RealThreadID;
        //This was checked already to be correct. No need to show extra code here for that.
        
        static bool once = true;

        double time = _get_time_ms();//A function that returns time based on QueryPerformanceCounter, in ms. Works perfectly.
        if (PostThreadMessage(dwTargetThreadID, INTER_MESSAGE, (WPARAM)time, 0))
        {
            printf("message send properly!");//This is always printed.
        }
        else if (once)
        {
            once = false;
            DWORD error = GetLastError();
            printf(error);//This is never printed.
        }
        Sleep(5);
    }
}

//This is the WndProc of the receiving thread with a Message-Only window.
LRESULT CALLBACK WndProcA(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    //Prep.//Knowing which thread we belong to. 
    switch (message)
    {
    case WM_INPUT:
    {
        //deleted code, but in the original code, this message is received perfectly.
        //I say it works perfectly so that you don't doubt the basic functioning of the thread, window, and messaging.
        break;
    }
    case INTER_MESSAGE:
    {       
        double sending_time = (double)wParam;
        double current_time = _get_time_ms();
        double vlu = current_time - sending_time;
        ThreadsMutexes_A.Lock();
        InterThreadMessagingReportObject->MessageEverReceived = true;//This is never turned true.
        InterThreadMessagingReportObject->Update(vlu);//Value is never updated and min max are fixed at their infinity initialization in the struct.
        ThreadsMutexes_A.Unlock();
        break;
    }
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
}

/*This is the function that prints results after the thread is terminated. (Note that the InterThreadMessagingReportObject
itself is a global variable, and is not deallocated when the thread is eliminated. It is perfectly readable)*/
void PrintResults()
{
    ThreadsMutexes_A.Lock();
    PrintTInteger("Messages received?: ", (InterThreadMessagingReportObject->MessageEverReceived) ? 1 : 0);
PrintTInteger("COUNT: ", InterThreadMessagingReportObject->Count);
PrintTFloat("AVERAGE: ", InterThreadMessagingReportObject->Average);
PrintTFloat("MIN: ", InterThreadMessagingReportObject->min);
PrintTFloat("MAX: ", InterThreadMessagingReportObject->max);
ThreadsMutexes_A.Unlock();
/*
Note that mutex was used here to make sure that the version of the global variable is visible everywhere and not only
local to the editing thread, by asking for an explicit synchronization when accessing data.
*/

/*
Result printed are these:

Messages received?: 0
COUNT: 0
AVERAGE: 0.000000
MIN: inf
MAX: -inf


*/
}

The final relevant information is that this code is run within UE4. The code is made fully with winapi style and not with UE. and is written into WindowsApplication.cpp file in the engine. I wonder if UE4 has some configurations that prevent inter-thread communication outside of the engine api and style of code.

>Solution :

The observed behavior follows the contract spelled out in the documentation for PostThreadMessage:

Messages sent1 by PostThreadMessage are not associated with a window. As a general rule, messages that are not associated with a window cannot be dispatched by the DispatchMessage function.

In other words: A message posted to a thread will not be observed in a window procedure of a window that happens to be owned by that thread.

The documentation also explains how to observe thread messages:

The thread to which the message is posted retrieves the message by calling the GetMessage or PeekMessage function.


1 That should read "posted", really.

Leave a Reply