For example, I have a main thread, there is created a lot of classes and etc. I have a network part, that wait for client data in separate thread. This "waiter" should run some functions from classes that was created in main thread and this functions should be executed in main thread.
How could I do so? If i call needed methods this way SomeClass::SomeMethod(some_args);
from waiter, sure, they executes in secondary thread.
Would be good have something like this:
SomeClass::Invoke(function_pointer);
so, the function that function_pointer points on would be executed in main thread? I need an advice for windows OS.
If this is Windows Win32 application, then using the application's Message processing queue is a common approach. In the main window of your app you wait for a custom user message, typically it will be something like:
(in header file)
#define WM_MYCUSTOMMESSAGE (WM_USER + 1)
(WndProc for you main window)
LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_MYCUSTOMMESSAGE:
... Process something
break;
}
}
(On seconday thread)
SendMessage(hWnd, WM_MYCUSOMMESSAGE, wParam, lParam); // Send and wait for the result
PostMessage(hWnd, WM_MYCUSTOMMESSAGE, wParam, lParam); // Send the message and continue this thread.
[EDIT] For a Console application, try using Windows Events. So create a named Event using:
(On primary thread)
HANDLE myEvent = CreateEvent(NULL, FALSE, FALSE, "MyEvent");
... later as part of a message processing loop
while(true)
{
WaitForSingleObject( myEvent, 0 ); // Block until event is triggers in secondary thread
... process messages here
... I recommend storing "messages" in a synchronized queue
}
(On secondary thread)
SetEvent(myEvent); // Triggers the event on the main thread.
Even with the invoke, the function would still execute in the thread it was called in, so that's of no use.
You can have a busy wait or a mutex, inside a loop, in the main thread that is released in the secondary threads, and when released, it calls some method depending on a ternary variable.
//thread1
runThread2();
while (true)
{
mutex.acquire();
mutex.lock();
switch(command)
{
case command_noop:
sleep(1000);
break;
case command1:
foo1();
break;
case command2:
foo2();
break;
//and so on...
}
mutex.release();
}
//thread2:
mutex.lock();
//commands
command = 1;
mutex.release();
mutex.acquire();
//rest of commands
In Embarcadero C++ Builder, there are functions TThread::Queue and TThread::Synchronize, which can be used to execute functions in the main thread. This works from any thread, it doesn't have to be a TThread
.
#include <vcl.h>
#include <functional>
namespace {
class wrapper : public TCppInterfacedObject<TThreadProcedure> {
public:
wrapper(std::function<void(void)> f) : f_(f) {}
void __fastcall Invoke() {
f_();
}
private:
std::function<void(void)> f_;
};
const unsigned int main_thread = GetCurrentThreadId();
} // namespace
// Execute the function asynchronously in main thread
void queue_to_main_thread(std::function<void(void)> f)
{
if (GetCurrentThreadId() == main_thread) {
f();
}
else {
TThread::Queue(NULL, _di_TThreadProcedure(new wrapper(f)));
}
}
// Execute the function synchronously in main thread
void synchronize_to_main_thread(std::function<void(void)> f)
{
if (GetCurrentThreadId() == main_thread) {
f();
}
else {
TThread::Synchronize(NULL, _di_TThreadProcedure(new wrapper(f)));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With