【问题标题】:Simplifying VCL thread wrapper code简化 VCL 线程包装器代码
【发布时间】:2013-05-22 17:56:11
【问题描述】:

我正在使用线程包装器,它检查是否从主线程调用了更新 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;
}

【问题讨论】:

    标签: multithreading synchronization c++builder vcl


    【解决方案1】:

    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);
    }
    

    【讨论】:

    • 谢谢,绝对是对我的版本的改进。
    • 不适用于 Builder C++ 6 [C++ Error] main.cpp(100): E2247 '_fastcall TThread::Synchronize(void (_fastcall * (_closure )())())' is not accessible
    • @AndreiKrasutski 正确,Synchronize()static 重载是在 Delphi 7 中添加的(因此,它直到 BDS 2006 才出现在 C++Builder 中)并且非静态重载是protected 在 C++Builder 6 中并且只能在 TThread 派生类中使用。有问题的代码使用UnicodeString,因此是RADStudio 2009 或更高版本,其中非静态重载为public
    猜你喜欢
    • 2012-09-17
    • 2011-03-04
    • 2018-05-19
    • 2017-04-17
    • 2011-08-09
    • 2014-02-24
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    相关资源
    最近更新 更多