0

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.
Physician
  • 483
  • 2
  • 7
  • Thread messages aren't associated with any window. If you post a thread message, that message is never dispatched to a window procedure. It can only be observed in the message loop that runs on the target thread. – IInspectable Apr 20 '23 at 11:20
  • @IInspectable Interesting. I use the thread ID to send message to it. How to associate the message with the window instead? – Physician Apr 20 '23 at 11:29
  • By calling [`PostMessage`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-postmessagew). The follow-up question (*"well, then, how do I obtain the `HWND`?"*) likely is too generic. To get that resolved, you'd have to provide more details. Ultimately, you'll have to communicate the "address" to the sender. There is more than one way to do that, but that's a different Q&A altogether. – IInspectable Apr 20 '23 at 11:37
  • @IInspectable Shit that is extremely obvious. Thanks a lot and sorry for taking from your time for such obvious mistake. My bad. – Physician Apr 20 '23 at 11:38

1 Answers1

1

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

Messages posted 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.

IInspectable
  • 46,945
  • 8
  • 85
  • 181