3

VCLを更新する関数(いくつかの引数もあります)がメインスレッドから呼び出されたかどうかをチェックし、常にメインスレッドのコンテキスト内で実行するスレッドラッパーを使用しています。

それは機能しますが、もっと簡単にしたいです。問題は、エラーが発生しやすい VCL 同期を必要とするすべての関数でこのコードを繰り返さなければならないことです。このラッパーをよりシンプルで再利用可能にする方法はありますか? この特定のラッパーは 1 つのパラメーターのみを使用しますが、コピーし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;
}
4

1 に答える 1

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);
}
于 2013-05-28T21:33:14.863 に答える