I want to do something like this:
void TForm2::SetMsg(UnicodeString fMsg)
{
// If thread is not main Queue...
if (GetCurrentThreadId() != System::MainThreadID)
{
TThread::Queue( nullptr, [&]() -> void { Form2->SetMsg(fMsg); } );
return;
}
// If thread is main then print directly...
Memo1->Lines->Add(fMsg);
}
So I simply call SetMsg("mymessage");
and regardless in which thread it is called from it prints properly. The above would work except the UnicodeString
gets deallocated before lambda is called.
It is my understanding that the lambda above should remain allocated in this form, and it indeed works if I hardcode the string in the lambda itself instead of fMsg parameter. So how do I pass the parameter then?
I could allocate it with new and delete later, but that fails for some reason too.
I tried:
void TForm2::SetMsg(UnicodeString fMsg)
{
// If thread is not main Queue...
if (GetCurrentThreadId() != System::MainThreadID)
{
UnicodeString* p = new UnicodeString(fMsg);
TThread::Queue( nullptr, [&]() -> void { try { Form2->SetMsg(*p); } __finally { delete p; } } );
return;
}
// If thread is main then print directly...
Memo1->Lines->Add(fMsg);
}
Would it be faster (less expensive) or easier with the TThread::CreateAnonymousThread
?
The first version works fine if TThread::Synchronize
is used but I want to avoid thread blocking.
Your lambda is capturing the
UnicodeString
by reference, so whenSetMsg()
exits, theUnicodeString
will be destroyed, leaving the reference inside the lambda dangling. The lambda needs to capture theUnicodeString
by value instead to make its own copy.Also, I would not recommend using the global
Form2
variable to callSetMsg()
on, I would have the lambda captureSetMsg
'sthis
pointer instead.Try this:
Alternatively, don't have the lambda call
SetMsg()
a second time, just access theMemo
directly instead, since you know theGetCurrentThreadId()
check will be redundant at that point:Your lambda is capturing the pointer by reference, so you are leaving the reference inside the lambda dangling when
SetMsg()
exits. You need to capture the pointer by value instead:In general, using a dynamic
UnicodeString
will work, though I would strongly suggest capturing astd::unique_ptr
orstd::shared_ptr
instead to handle the deallocation for you, instead of using a manualtry/__finally
block:No. You are already running in a thread when calling
Queue()
, there is no reason to waste overhead spawning another thread. And you would still have to deal with copying values into that thread's lambda/callback function.