Embarcadero TThread:用C++传递TThreadMethod

Jam*_*gle -1 c++ delphi c++builder-xe8

编辑:现在我对发生的事情有了更好的了解,我想我可以更好地说出这个问题,因此它更有用.

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

TThread.Queue(nil, 
    procedure
    begin
        LogMessage("test");
    end
    );
Run Code Online (Sandbox Code Playgroud)

代码的目的是调用一个TMemo以线程安全的方式更新表单的方法.这是我试图调用的方法的C++版本Thread.Queue

void __fastcall TClientForm::LogMessage( String message )
{
    MemoLog->Lines->Add( message );
}
Run Code Online (Sandbox Code Playgroud)

因为我使用的是没有CLANG增强功能的BCC32编译器,所以不能使用Lambda.相反,根据这个文档,我需要创建一个继承TThreadProcedureInvoke()方法来覆盖方法来完成我需要完成的工作.然后我可以将该类的实例传递给TThread::Queue.

我创建了以下继承TThreadProcuedure并包含invoke方法的类.

class TMyThreadProcedure : TThreadProcedure
{
    void __fastcall Invoke( String message );
};
Run Code Online (Sandbox Code Playgroud)

但是,由于TThreadProcedure是一个抽象类,我不能简单地创建它的实例来传递TThread::Queue.TThreadProcedure当我将类的实例传递到其中时,继承和定义要调用的函数的正确方法是什么TThread::Queue

Rem*_*eau 6

如文档中所述:

如何在C++中处理Delphi匿名方法

你有两个选择:

  1. 派生一个实现适当接口(在本例中为)的类1Classes::TThreadProcedure,覆盖该Invoke()方法以完成您想要的工作.然后,您可以将该类的实例传递给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)
        )
    );
    
    Run Code Online (Sandbox Code Playgroud)

    (1文档中其他部分的使用TCppInterfacedObjectINTFOBJECT_IMPL_IUNKNOWN涵盖:继承和接口)

    TMethodRef如果您需要在代码的多个位置使用匿名方法/过程,那么该文档还提供了可重用的类来帮助实现:

    使用Functor(函数对象)

    例如:

    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)
            )
        )
    );
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在仅基于Clang的C++ 11编译器中,您可以在任何需要匿名过程/方法的地方使用C++ lambda:

    TThread::Queue(NULL, 
        [this]() -> void { LogMessage("test"); }
    );
    
    Run Code Online (Sandbox Code Playgroud)