delphi — Embarcadero TThread: передать метод TThread в метод переполнения стека

Редактировать:
Теперь, когда у меня есть лучшее представление о том, что происходит, я думаю, что могу лучше сформулировать этот вопрос, чтобы он был более полезным.

Я пытаюсь повторить следующий код Delphi в C ++

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

Целью кода является вызов метода, который обновляет TMemo на форме в потоке безопасным способом. Вот C ++ версия метода, с которым я пытаюсь вызвать Thread.Queue

void __fastcall TClientForm::LogMessage( String message )
{
MemoLog->Lines->Add( message );
}

Поскольку я использую компилятор BCC32 без улучшений CLANG, использование Lambda не вариант. Вместо этого согласно эта документация Мне нужно создать класс, который наследует от TThreadProcedure который переопределяет Invoke() способ сделать работу мне нужно сделать. Затем я могу передать экземпляр этого класса в TThread::Queue,

Я создал следующий класс, который наследует TThreadProcuedure и содержит метод вызова.

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

Тем не менее, так как TThreadProcedure это абстрактный класс, я не могу просто создать его экземпляр для передачи в TThread::Queue, Как правильно наследовать от TThreadProcedure и определить функцию, которая будет вызываться, когда я передаю экземпляр моего класса в TThread::Queue?

0

Решение

Как указано в документации:

Как обрабатывать анонимные методы Delphi в C ++

У вас есть два варианта:

  1. вывести класс 1 который реализует соответствующий интерфейс (в этом случае Classes::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)
    )
    );
    

    (1 использование TCppInterfacedObject а также INTFOBJECT_IMPL_IUNKNOWN рассматривается в другом месте в документации: Наследование и интерфейсы)

    Документация также предоставляет многоразовые TMethodRef класс, чтобы помочь с реализацией, если вам нужно использовать анонимные методы / процедуры в нескольких местах вашего кода:

    Использование функтора (объекта функции)

    Например:

    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 компиляторы C ++ 11 только вы можете использовать лямбду C ++ везде, где ожидается анонимная процедура / метод:

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]