问题描述
我正在使用线程包装器,它检查是否从主线程调用了更新VCL(也有一些参数)的函数,然后始终在主线程的上下文中执行.
I am using thread wrapper which checks if function which updates VCL (which also has some arguments) was called from main thread or not and then executes in within the context of Main thread always.
它可以工作,但我想使其更简单.问题是我必须在每个需要VCL同步的函数中都重复此代码,这容易出错.有没有办法使这个包装器更简单,更可重用?请注意,这个特定的包装器仅使用一个参数,但是可以将任意数量的参数复制到TLocalArgs
并继续传递.
It works but I want to make it simpler. The problem is that I have to repeat this code in every function which needs VCL synchronization which is prone to errors. Is there a way to make this wrapper simpler and more re-useable? Note that this particular wrapper only uses one parameter but there can be any number of parameters which are copied to TLocalArgs
and passed on.
当前代码:
boost::scoped_ptr<TIdThreadComponent> WorkerThread;
...
void TForm1::SetMemoMessage(UnicodeString Msg)
{
// Check which thread called function, main thread or worker thread
if (GetCurrentThreadId() != System::MainThreadID)
{
struct TLocalArgs
{
TForm1 *Form;
UnicodeString Msg;
void __fastcall SetMemoMessage() // Same name as main function to make it easier to maintain
{
// We are in main thread now, safe to call message update directly
Form->SetMemoMessage(Msg);
}
};
// We are in worker thread, wrap into Synchronize
TLocalArgs Args = { this, Msg };
WorkerThread->Synchronize(&Args.SetMemoMessage);
return;
}
// MAIN THREAD CODE is very simple compared to wrapper above
Memo1->Text = Msg;
}
推荐答案
TThread::Synchronize()
在内部为您检查MainThreadID
,如果从主线程调用Synchronize()
则直接调用指定的过程.因此,只需无条件调用Synchronize()
并让其处理细节即可. Synchronize()
还提供了重载的静态版本,因此您甚至不需要TThread
指针即可调用它.
TThread::Synchronize()
checks MainThreadID
internally for you and calls the specified procedure directly if Synchronize()
is called from the main thread. So just call Synchronize()
unconditionally and let it handle the details. Synchronize()
also has overloaded static versions available so you don't even need a TThread
pointer to call it.
尝试一下:
void TForm1::SetMemoMessage(UnicodeString Msg)
{
struct TLocalArgs
{
UnicodeString Msg;
void __fastcall SetMemoMessage()
{
Form1->Memo1->Text = Msg;
}
};
TLocalArgs Args;
Args.Msg = Msg;
TThread::Synchronize(NULL, &Args.SetMemoMessage);
}
这篇关于简化VCL线程包装器代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!