Embarcadero TThread:在 C++ 中传递 TThreadMethod

Embarcadero TThread: Pass TThreadMethod in C++

编辑: 现在我对正在发生的事情有了更好的了解,我想我可以更好地表达这个问题,这样它就更有用了。

我正在尝试在 C++ 中复制以下 delphi 代码

TThread.Queue(nil, 
    procedure
    begin
        LogMessage("test");
    end
    );

代码的目的是调用一种方法,以线程安全的方式更新表单上的 TMemo。这是我尝试使用 Thread.Queue

调用的方法的 C++ 版本
void __fastcall TClientForm::LogMessage( String message )
{
    MemoLog->Lines->Add( message );
}

因为我使用的是没有 CLANG 增强功能的 BCC32 编译器,所以不能选择使用 Lambda。相反,根据 this documentation,我需要创建一个继承自 TThreadProcedure 的 class,它会覆盖 Invoke() 方法来完成我需要完成的工作。然后我可以将 class 的一个实例传递给 TThread::Queue

我创建了以下 class,它继承了 TThreadProcuedure 并包含一个调用方法。

class TMyThreadProcedure : TThreadProcedure
{
    void __fastcall Invoke( String message );
};

但是,由于 TThreadProcedure 是一个抽象 class,我不能简单地创建它的一个实例来传递给 TThread::Queue。当我将 class 的实例传递给 TThread::Queue 时,从 TThreadProcedure 继承并定义要调用的函数的正确方法是什么?

如文档中所述:

How to Handle Delphi Anonymous Methods in C++

你有两个选择:

  1. 派生一个 class 1 实现适当的接口(在这种情况下,Classes::TThreadProcedure),覆盖 Invoke() 方法来完成您想要的工作。然后,您可以将 class 的一个实例传递给 TThread::Queue()。例如:

    class TLogMessageRef : public TCppInterfacedObject<Classes::TThreadProcedure>
    {
    private:
        TClientForm *form;
    public:
        TLogMessageRef(TClientForm* _form) : form(_form) {}
        INTFOBJECT_IMPL_IUNKNOWN(TInterfacedObject);
    
        void __fastcall Invoke()
        {
            form->LogMessage("test");
        }
    };
    
    TThread::Queue(NULL,
        Classes::_di_TThreadProcedure(
            new TLogMessageRef(this)
        )
    );
    

    (1的使用TCppInterfacedObject and INTFOBJECT_IMPL_IUNKNOWN is covered elsewhere in the documentation: Inheritance and Interfaces)

    文档还提供了一个可重用的 TMethodRef class 来帮助实现,如果您需要在代码的多个地方使用匿名 methods/procedures:

    Using a Functor (Function Object)

    例如:

    struct LogMsg
    {
        TClientForm* form;
        LogMsg(TClientForm *_form) : form(_form) {}
        void operator()()
        {
            form->LogMessage("test");
        }
    };
    
    typedef TMethodRef<Classes::TThreadProcedure, LogMsg, void> MyMethRef;
    
    TThread::Queue(NULL,
        Classes::_di_TThreadProcedure(
            new MyMethRef(
                LogMsg(this)
            )
        )
    );
    
  2. 仅在 Clang-based C++11 compilers 中,您可以在任何需要匿名 procedure/method 的地方使用 C++ lambda:

    TThread::Queue(NULL, 
        [this]() -> void { LogMessage("test"); }
    );