Home > Enterprise >  How to return a WM_COPYDATA message instantly and also call a function?
How to return a WM_COPYDATA message instantly and also call a function?

Time:09-22

How to return a response when receiving a WM_COPYDATA message 'instantly' and also call a function?

I tried to use chrono but the app that sent the message only receive a response after the sendCommand function has been executed.

#include <thread>
#include <future>
#include <iostream>

void sendCommand(std::chrono::seconds delay, std::string cmd)
{
     std::this_thread::sleep_for( delay );
     std::cout << "\nThe waited command is =" << cmd;
}


switch (msg)
{
    case WM_COPYDATA:
    {
        OutputDebugStringW(L"\nWM_COPYDATA!");
        PCOPYDATASTRUCT pcds = reinterpret_cast<PCOPYDATASTRUCT>(lParam);
        //....

        auto s1 = std::async(std::launch::async, sendCommand, std::chrono::seconds(5), "Command1");

        return 1;
    }
}

CodePudding user response:

If you don't mind blocking the thread that received the WM_COPYDATA, you could simply use ReplyMessage():

#include <iostream>

void sendCommand(std::chrono::seconds delay, std::string cmd)
{
    std::this_thread::sleep_for( delay );
    std::cout << "\nThe waited command is =" << cmd;
} 

switch (msg)
{
    case WM_COPYDATA:
    {
        OutputDebugStringW(L"WM_COPYDATA!");
        PCOPYDATASTRUCT pcds = reinterpret_cast<PCOPYDATASTRUCT>(lParam);
        //...

        ReplyMessage(1);
        sendCommand(std::chrono::seconds(5), "Command1");

        return 1;
    }
}

CodePudding user response:

What you're looking for is called a lambda function (https://en.cppreference.com/w/cpp/language/lambda) and looks like this:

With std::thread:

  std::thread t([]
  {
    sendCommand(std::chrono::seconds(5), "Command1");
  });

With std::async Solution with shared future, by capturing it the lifetime of the future is extended to the life time of the lambda. If you're on windows/msvc this has the small benefit of using a thread from a threadpool. Otherwise just use the thread solution.

    #include <memory> 
    
    auto ft = std::make_shared<std::future<void>>();
    *ft = std::async(std::launch::async, [ft]    
    {
        sendCommand(std::chrono::seconds(5), "Command1");
    });

CodePudding user response:

In this answer, I am assuming that you don't want to discard the data sent by WM_COPYDATA, but that you want the function that you are calling to have access to this data.

It is not necessary to use multi-threading to solve this problem, if you allow the WM_COPYDATA handler to copy the data before returning.

What the WM_COPYDATA handler could do is

  1. dynamically allocate memory for copying the data,
  2. then actually copy the data,
  3. then post a user-defined message containg a pointer to the copied data to the message queue using PostMessage,
  4. then return immediately, without calling the function to process the data.

When handling the user-defined message later in the thread's message loop, the handler to the user-defined message could then call the function to process the data and then, after the function returns, free the dynamically allocated data.

It is necessary to copy the data inside the WM_COPYDATA handler, because the pointer to the data becomes invalid as soon as the handler returns.

  • Related