2015-09-26 3 views
1

Я использую C++ в течение длительного времени, и я не очень хорошо разбираюсь в Delphi (XE). Но по какой-то причине я должен перенести свой код на C++ в Delphi для реализации следующей задачи. У меня есть основной TForm, который я получил от кого-то другого. В TForm у меня есть 2 частных объекта и процедуры, определенные для завершения некоторой задачи. Моя задача - создать поток для вызова этих классов и процедур для некоторых вычислений.Создание потока для доступа к процедурам и переменным другого класса

TASKForm = class(TForm) 
    private 
    MonitorA :TMonClassA; 
    ConstB :TConstClassB; 

    procedure calculateStmp; 
end; 

Эта задача может быть легко сделать в C++, если я расширяю TASKForm с несколькими наследования. Но после некоторых исследований я обнаружил, что Delphi этого не поддерживает. Поэтому мне нужно думать о другом. Затем я увидел статью об использовании вложенного класса.

TASKForm = class(TForm) 
    protected 
    TMyThread = class(TThread) 
     public 
     procedure Execute(); override; // inside this I need to call TASKForm.MonitorA.somemethod, TASKForm.ConstB.somemethod and TASKForm.calculateStmp 
    end 
    private 
    MonitorA :TMonClassA; 
    ConstB :TConstClassB; 

    procedure calculateStmp; 
end; 

Но вскоре я обнаружил, что процедура, определенная в вложенном классе, не может получить доступ к закрытым членам контейнера. Интересно, есть ли другой способ создать поток для вызова частных функций и переменных одного класса? Благодарю.


обновленный код. Я пробую еще две схемы. Первый из них - использовать интерфейс, такой как

TmyThread = interface(TThread) 
end; 

TASKForm = class(TForm, TmyThread) 
private 
    MonitorA :TMonClassA; 
    ConstB :TConstClassB; 

    procedure calculateStmp; 
end; 

Но это не работает, потому что TThread не является типом интерфейса. Я пытаюсь использовать Application.ProcessMessages, как следующий

procedure TASKForm.RunMyTask; 
    while (not RunTerminated) do // RunTerminated will be set when an external event triggered 
    begin 
    MonitorA.Somemethod; 
    calculateStmp; 
    ConstB.Somemethod; 
    Application.ProcessMessages; 
    end; 
end 

скажу этот метод «хорошо», но не идеально, потому что MonitorA.Somemethod и ConstB.Somemethod может занять длительное или короткое время запуска (время не является постоянным), поэтому иногда, когда внешнее событие запускается для установки RunTerminated True, оно не будет немедленно завершать цикл while. Я все еще ищу метод многопоточности.

+0

Delphi поддерживает множественное наследование, но только при использовании интерфейсов. Класс Delphi может иметь только 1 конкретный базовый класс, но может реализовывать несколько интерфейсов. Таким образом, вы можете определить интерфейс для доступа к своим членам. Или вы можете просто передать их как параметры конструктору класса потока. –

+0

Спасибо Реми. Я пробую код (просто добавленный), но он сказал, что TThread не является типом интерфейса, поэтому я не могу добавить интерфейс в свой класс формы. Я что-то пропустил в своем коде. – user1285419

+0

'TThread' - это конкретный класс, а не интерфейс. Вы не можете наследовать 'TASKForm' из' TForm' и 'TThread'.Суть моего предыдущего предложения состояла в том, чтобы вы определили пользовательский интерфейс, который предоставляет доступ для ваших частных членов, а затем TASKForm может реализовать эти аксессоры. Затем передайте интерфейс TASKForm'а в поток, чтобы он мог получить доступ к членам, когда это необходимо. –

ответ

0

Отредактировано в свете комментариев Дэвида Хеффернана.

Шаг 1. Создайте потомка TThread с процедурой обратного вызова - как этот

type 
    TOnMyExecute = procedure(Sender : TObject) of object; // sender not required here but is convention 

    TMyThread = class(TThread) 
    private 
     fMyOnExecute : TOnMyExecute; 
    public 
    procedure Execute(); override; // inside this I need to call TASKForm.MonitorA.somemethod, TASKForm.ConstB.somemethod and TASKForm.calculateStmp 
    property MyOnExecute : TMyOnExecute read fMyOnExecute write fMyOnExecute; 
    end; 

Шаг 2 Создайте свой потомок TForm довольно много, как раньше.

TASKForm = class(TForm) 
    protected 
    MyThread : TMyThread; 
    private 
    MonitorA :TMonClassA; 
    ConstB :TConstClassB; 

    procedure calculateStmp; 
    procedure MyPrivateActions(Sender : TObject); 
end; 

Где-то, вероятно, в TaskForm.Create или когда поток запускается присвоению MyPrivateActions к MyTask.MyOnExecute

MyTask.MyOnExecute := MyPrivateActions; 

Наконец TMyThread OnExecute выглядит следующим образом

TMyThread.OnExecute; 
begin 
    if assigned(fMyOnExecute) then 
    begin 
    fMyOnExecute(self); 
    end; 
end; 

Дело в том, что хотя поток выполняет функцию, функция принадлежит форме, которая может обращаться к своим собственным частным членам.

+0

XE pre-date библиотека потоковой обработки –

+0

TThead использовался в вопросе – Dsm

+0

Действительно. Конечно, ваш код использует 'TTask'. Что происходит из библиотеки потоков. Какой XE нет. Библиотека потоков была представлена ​​в XE7. И даже поэтому 'TTask' не следует подклассифицировать. Более того, я не думаю, что у него есть виртуальный метод 'Execute'. Вы имели в виду 'TThread', а не' TTask'? –