Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.11.2015, 23:15   #1
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию Завершил ли поток свою работу?

Привет.

Делаю так:

Код:
var
  Check: array of TCheck;

procedure TForm1.btn1Click(Sender: TObject);
  var
    i : Integer;
begin
  SetLength( Check, 10 );
  for i := 0 to Length(Check) - 1 do begin
    Check[i] := TCheck.Create(True);
    Check[i].FreeOnTerminate := True;
    Check[i].Priority := tpNormal;
    Check[i].Resume;
  end;
end;
Как узнать, что какой-то элемент массива Check уже завершил свою работу в потоке?

Например, я дал работу этим 10 потокам. Какой-то поток справился быстрее всех. В OnTerminate проверяем есть ли еще работа. Если есть, то запускаем еще 1 поток для выполнения под тем же индексом в массиве Check, что и завершенный.

Что-то вроде:

Код:
for i := 0 to Length(Check) - 1 do
  if Check[i].Terminated then begin
     Check[i] := TCheck.Create(True);
     Check[i].FreeOnTerminate := True;
     Check[i].Priority := tpNormal;
     Check[i].Resume;
  end;
bilibian вне форума Ответить с цитированием
Старый 28.11.2015, 00:05   #2
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

не читая вопроса, сразу говорю: замени
Код:
var
  Check: array of TCheck;
на
Код:
var
  Check: TThreadList;
Ещё лучше – напиши наследника от TObjectList<TThread>. Дальнейшая работа с тредами сразу упростится.

Читаю дальше...
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 28.11.2015, 00:06   #3
come-on
Участник клуба
 
Регистрация: 21.10.2015
Сообщений: 1,361
По умолчанию

Может вам про пул потоков посмотреть, и воспользоваться каким готовым?
come-on вне форума Ответить с цитированием
Старый 28.11.2015, 00:10   #4
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

Цитата:
Как узнать, что какой-то элемент массива Check уже завершил свою работу в потоке?
дык, в OnTerminate жэж попадает указатель на вызывающий событие объект! и только после возврата из обработчика срабатывает деструктор, если FreeOnTerminate.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 28.11.2015, 02:08   #5
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию

Цитата:
Сообщение от min@y™ Посмотреть сообщение
дык, в OnTerminate жэж попадает указатель на вызывающий событие объект! и только после возврата из обработчика срабатывает деструктор, если FreeOnTerminate.
А как мне получить указатель в OnTerminate на текущий тред?

Код:
var
  Check: array of TCheck;

procedure TForm1.btn1Click(Sender: TObject);
  var
    i : Integer;
begin
  SetLength( Check, 10 );
  for i := 0 to Length(Check) - 1 do begin
    Check[i] := TCheck.Create(True);
    Check[i].FreeOnTerminate := True;
    Check[i].OnTerminate := Term;
    Check[i].myindex := i;
    Check[i].Priority := tpNormal;
    Check[i].Resume;
  end;
end;

procedure TForm1.Term(Sender: TObject);
begin
  Check[ Check[?].myindex ] := nil;
end;

Последний раз редактировалось bilibian; 28.11.2015 в 02:37. Причина: TCheck поменял на TForm1
bilibian вне форума Ответить с цитированием
Старый 28.11.2015, 02:21   #6
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию

Цитата:
Сообщение от min@y™ Посмотреть сообщение
не читая вопроса, сразу говорю: замени
Код:
var
  Check: array of TCheck;
на
Код:
var
  Check: TThreadList;

А в деструкторе треда корректно ли удалять элементы этого списка?


Код:
destructor TCheck.Destroy;
begin
  with Check.LockList do
    try
      Delete(myindex);
    finally
      Check.UnlockList;
    end;
end;
bilibian вне форума Ответить с цитированием
Старый 28.11.2015, 02:22   #7
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

Цитата:
А как мне получить указатель в OnTerminate на текущий тред?
Sender.
Код:
procedure TCheck.Term(Sender: TObject);
var
  idx: Integer;
begin
  // если заменишь массив на список:
  idx:= Check.IndexOf(Sender);
  if idx <> -1
    then Check.Delete(idx);
end;
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 28.11.2015, 02:25   #8
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

Цитата:
А в деструкторе треда корректно ли удалять элементы этого списка?
не надо удалять в деструкторе ничего, кроме дочерних объектов. иначе высока вероятность долгого секса с дебаггером.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 28.11.2015, 02:33   #9
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

вот кусок моего древнего проекта времён delphi 7.
Код:
  // Класс - очередь потоков, исполняющий их один за другим по порядку
  TThreadQueue = class(TObjectQueue)
  private
    FInProgress: Boolean;
    FCurrentThread: TThread;
    procedure OnThreadTerminate(Sender: TObject);
  public
    constructor Create;
    destructor Destroy; override;

    procedure ExecuteThreads;
    procedure TerminateCurrentThread;
    procedure TerminateAllThreads;

    property InProgress: Boolean read FInProgress;
    property CurrentThread: TThread read FCurrentThread;
  end;

implementation

{ TThreadQueue }

constructor TThreadQueue.Create;
begin
  inherited;
  FInProgress:= False;
  FCurrentThread:= nil;
end;

destructor TThreadQueue.Destroy;
begin
  if Assigned(FCurrentThread)
    then begin
           FCurrentThread.OnTerminate:= nil;
           FCurrentThread.Terminate();
         end;

  while Count <> 0 do
    TThread(Pop()).Free();

  inherited;
end;

procedure TThreadQueue.ExecuteThreads;
begin
  if (Self.Count <> 0) 
    then begin
           FInProgress:= True;
           FCurrentThread:= TThread(Pop());
           FCurrentThread.OnTerminate:= OnThreadTerminate;
           FCurrentThread.Resume();
         end
    else FInProgress:= False;
end;

procedure TThreadQueue.OnThreadTerminate(Sender: TObject);
begin
  FCurrentThread:= nil;
  ExecuteThreads();
end;

procedure TThreadQueue.TerminateCurrentThread;
begin
  if Assigned(FCurrentThread)
    then FCurrentThread.Terminate();
end;

procedure TThreadQueue.TerminateAllThreads;
var
  T: TThread;
begin
  // очистка очереди
  if Assigned(FCurrentThread)
    then begin
           FCurrentThread.OnTerminate:= nil;
           FCurrentThread.Terminate();
           FCurrentThread:= nil;
         end;

  while Self.Count <> 0 do
    begin
      T:= TThread(Self.Pop());
      T.Free();
    end;

  FInProgress:= False;
end;
Caution! This source is not for copypaste!
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 28.11.2015, 03:36   #10
bilibian
Форумчанин
 
Регистрация: 21.01.2014
Сообщений: 389
По умолчанию

При создании потока у меня передается много параметров в поток.

Код:
var
  Check: array of TCheck;

procedure TForm1.btn1Click(Sender: TObject);
  var
    i : Integer;
begin
  SetLength( Check, 10 );
  for i := 0 to Length(Check) - 1 do begin
    Check[i] := TCheck.Create(True);
    Check[i].FreeOnTerminate := True;
    Check[i].p1 := param1;
    Check[i].p2 := param2;
    Check[i].p3 := param3;
    Check[i].Priority := tpNormal;
    Check[i].Resume;
  end;
end;
В случае, если я заменю:

Код:
var
  Check: array of TCheck;
на:

Код:
var
  Check: TThreadList;
То как мне создать поток с помощью списка и передать все эти параметры?

Код:
var
  Check: TThreadList;

procedure TForm1.btn1Click(Sender: TObject);
begin
  Check := TThreadList.Create;
  Check.Add( TCheck.Create(param1,param2,param3) );
end;

var
  param1,param2,param3:string  

constructor TCheck.Create(param1,param2,param3:string);
begin
  inherited;
  p1 := param1;
  p2 := param2;
  p3 := param3;
end;
bilibian вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как заставить поток ждать пока браузер завершит свою работу bilibian Общие вопросы Delphi 4 10.11.2015 15:33
Раз в сутки программа на C# сама завершает свою работу TengiZ C# (си шарп) 22 02.05.2012 14:53
Как определить закончил ли работу поток? fredwriter Помощь студентам 13 01.12.2011 23:04
при каких условиях алгоритм закончит свою работу? незнайка_на_земле Помощь студентам 3 08.03.2011 00:40
Поток. Не получается создать поток. Выдает ошибки при запуске bigory Общие вопросы по Java, Java SE, Kotlin 3 23.09.2010 00:40