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
UnicodeStringby reference, so whenSetMsg()exits, theUnicodeStringwill be destroyed, leaving the reference inside the lambda dangling. The lambda needs to capture theUnicodeStringby value instead to make its own copy.Also, I would not recommend using the global
Form2variable to callSetMsg()on, I would have the lambda captureSetMsg'sthispointer instead.Try this:
Alternatively, don't have the lambda call
SetMsg()a second time, just access theMemodirectly 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
UnicodeStringwill work, though I would strongly suggest capturing astd::unique_ptrorstd::shared_ptrinstead to handle the deallocation for you, instead of using a manualtry/__finallyblock: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.