Нужна помощь профессионального программиста - страница 3

 
Vitalii Ananev #:

Вроде там есть обработчик OnTerminate срабатывать должен именно тогда когда поток завершил работу. Можно вызвать метод Terminate, а в OnTerminate очищать память.

Например так FExpert.OnTerminate :=FreeAndNil();

Вам еще нужно предусмотреть завершение всех дочерних потоков при завершении главного потока.

Я могу и ошибаться, но событие  OnTerminate у потока сработает только если он закончил выполнять метод Execute поэтому нужно в этом методе проверять если Terminated равен true то тут надо решить или продолжить выполнять метод Execute или принудительно из него выйти. В общем если Terminated равен true это еще не значит, что поток закончил выполнять метод Execute.

И как это проверить?

 
prostotrader #:

И как это проверить?

Опытным путем только. У меня сейчас работа такая, что я уже года три ни чего серьезного не писал кроме скриптов для квика и советников для мкл и многие навыки утеряны.

Terminated устанавливается равным труе если был вызван метод Terminate. Но фактическое прекращение работы будет именно когда будет закончен выполнятся код в Execute. Terminated = true это как бы просто флаг сигнализирующий  о том что инициировано принудительное завершение остановки процесса.

можно сделать так:

в Execute в начале метода  или в конце метода написать if Terminated then exit; А в OnTerminate чистить память.

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

 
Vitalii Ananev #:

Опытным путем только. У меня сейчас работа такая, что я уже года три ни чего серьезного не писал кроме скриптов для квика и советников для мкл и многие навыки утеряны.

Terminated устанавливается равным труе если был вызван метод Terminate. Но фактическое прекращение работы будет именно когда будет закончен выполнятся код в Execute. Terminated = true это как бы просто флаг сигнализирующий  о том что инициировано принудительное завершение остановки процесса.

можно сделать так:

в Execute в начале метода  или в конце метода написать if Terminated then exit; А в OnTerminate чистить память.

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

Я не управляю всеми потоками из главного окна.

Каждое дочернее окно создает свой поток, а при закрытии удаляет его.

procedure TExpert.Execute;
var
  aState: boolean;
begin
  while not Terminated do
  begin
    Mutex.Lock;
    try
      aState:= TransBusy;
    finally
      Mutex.Unlock;
    end;
    if(aState = false) then //No transactions
    begin
      Mutex.Lock;
      try
        aState:= DoOnTick;
        if(DoOnTick = true) then FDoOnTick:= false; //Reset flag
      finally
        Mutex.Unlock;
      end;
      if(aState = true) then
        begin
          UpdExpertData();
          OnTick();
        end;
    end else
    begin
      Mutex.Lock;
      try
        aState:= DoOnTrade;
        if(DoOnTrade = true) then FDoOnTrade:= false; //Reset flag
      finally
        Mutex.Unlock;
      end;
      if(aState = true) then OnTrade();
    end;
  end;
end;

Вопрос состоит в том Termineted гарантирует завершение Execute  или нет.

 
prostotrader #:

Я не управляю всеми потоками из главного окна.

Каждое дочернее окно создает свой поток, а при закрытии удаляет его.

....

Тут нет особой разницы из главного окна или из дочерних. У вас все дочерние окна создаются в рамках главного потока.

prostotrader #:


Вопрос состоит в том Termineted гарантирует завершение Execute  или нет.

Судя по коду у вас уже есть в методе Execute проверка инициировано ли завершение работы потока (while not Terminated do) . Работа потока зациклена пока не вызван метод Terminate, который установит Termineted равным true и цикл уже не выполнится тем самым будет завершен метод Execute .  Теперь для класса TThread создайте обработчик события OnTerminate и в нем уже освобождайте все ресурсы задействованные в работе потока.

 
Vitalii Ananev #:

Тут нет особой разницы из главного окна или из дочерних. У вас все дочерние окна создаются в рамках главного потока.

Судя по коду у вас уже есть в методе Execute проверка инициировано ли завершение работы потока (while not Terminated do) . Работа потока зациклена пока не вызван метод Terminate, который установит Termineted равным true и цикл уже не выполнится тем самым будет завершен метод Execute .  Теперь дя класса TThread создайте обработчик события OnTerminate и в нем уже освобождайте все ресурсы задействованные в работе потока.

Там нет ресурсов, просто вычисления

 
prostotrader #:

Там нет ресурсов, просто вычисления

Тогда просто поток.free. Или еще проще создать поток с FreeOnTerminate=true. Тогда поток будет уничтожен автоматически после завершения метода Execute. А у вас метод Execute завершается только если 

Terminated = true. Тогда при закрытии дочернего окна надо будет только написать поток.Terminate.
 
Михаил, а делегаты в дельфи есть? Или аналоги.
 
Dmitriy Skub #:
Михаил, а делегаты в дельфи есть? Или аналоги.

Если Вы это

https://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_Implements_for_Delegation

имеете ввиду, то есть.

Добавлено

Мне вообще-то все-равно в какой среде писать, просто на Делфи получаются нативные приложения

и привык уже...  К тому же уже все переписано. :)

 
Vitalii Ananev #:

Тогда просто поток.free. Или еще проще создать поток с FreeOnTerminate=true. Тогда поток будет уничтожен автоматически после завершения метода Execute. А у вас метод Execute завершается только если 

Terminated = true. Тогда при закрытии дочернего окна надо будет только написать поток.Terminate.

Ок.

Самое смешное, что переписал на потоки, а изначальная проблема осталась :)

procedure TMDIChild.OnData;
begin  //resive data
  FExpert.FinData:= TTransData(Data^);
  FExpert.UpdExpertData();
end;

Приходится здесь же парсить данные :)

 
prostotrader #:

Ок.

Самое смешное, что переписал на потоки, а изначальная проблема осталась :)

Приходится здесь же парсить данные :)

А сделать парсинг данных в потоке, есть возможность?

Причина обращения: