我正在使用线程包装器来检查是否从主线程调用了更新VCL(也有一些参数)的函数,然后在主线程的上下文中执行。
它有效,但我想让它变得更简单。问题是我必须在需要VCL同步的每个函数中重复此代码,这很容易出错。有没有办法让这个包装器更简单,更可重用?请注意,此特定包装器仅使用一个参数,但可以将任意数量的参数复制到TLocalArgs
并传递。
当前代码:
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;
}
答案 0 :(得分:6)
TThread::Synchronize()
在内部为您检查MainThreadID
,如果从主线程调用Synchronize()
,则直接调用指定的过程。所以只需无条件地调用Synchronize()
并让它处理细节。 Synchronize()
也有重载的静态版本可用,因此您甚至不需要TThread
指针来调用它。
试试这个:
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);
}