Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > Запустить процедуру по завершению потока


Автор: Bose 7.2.2006, 17:01
Собственно сабж.

Есть простой способ это сделать без извратов с Messageами? smile

Автор: _hunter 7.2.2006, 17:06
сам организуй обмен -- держи общий ресурс ( список/очередь ) и пиши в него из потоков. а какой-нит менеджер будет читать...

Автор: Bose 7.2.2006, 17:17
Цитата(_hunter @ 7.2.2006, 17:06 Найти цитируемый пост)

а какой-нит менеджер будет читать...


Нужно, чтобы форма вызвала процедуру, после того как поток уже полностью отработает... Пока что сделал, чтобы в Поток.ОнТерминэйт включался таймер, а сама процедура запускалась уже из таймера...
Просто интересно, может быть есть какое-то более элегантное решение smile

Автор: _hunter 7.2.2006, 17:29
более элегантное решение ( в данной ситуации ) -- послать форме сообщение.

Автор: Bose 7.2.2006, 17:52
Цитата(_hunter @ 7.2.2006, 17:29 Найти цитируемый пост)

послать форме сообщение.

smile
мне не очень хочется связываться с сообщениями...

Автор: _hunter 7.2.2006, 18:29
и чем это нежелание обосновано?

Автор: Bose 7.2.2006, 19:08
во-первых жутким страхом новизны smile
во-вторых, поверхностным знанием темы: не хочется попасть в ситуацию, когда сгенерированный мной Message(WM_USER+999 например), уже будет использоваться другим приложением
в-третьих: мне кажется, что Messageи стоит использовать в тех случаях, когда без них ну никак не обойтись - например для оповещения других(своих) приложений или форм, до которых средствами Дельфей не добраться..
в-четвертых: imho использование Messageй сродни использованию оператора Goto... будет сложнее ориентироваться в коде и отслеживать ошибки..
в-пятых: в данном конкретном случае, такой вызов надо сделать всего один раз

Автор: _hunter 7.2.2006, 19:28
страхи нужно преодолевать smile
а с какой стати кто-то будет слать твоей программе свое сообщение?
а тут другими средствами ( не считая синхронизации ) и не доберешся... делегатов в делфи нету.
введение потоков так же ( и таким же образом ) усложняет ориентирование.
поэтому послать сообщение проще, чем заморачиваться с синхронизацией.

Автор: Bose 7.2.2006, 19:41
Цитата(_hunter @ 7.2.2006, 19:28 Найти цитируемый пост)

а с какой стати кто-то будет слать твоей программе свое сообщение?
т.е. сообщение не могут гулять по системе свободно? в смысле, никто не может послать сообщение м таким номером который воспринимает моя программа в "широковещательном режиме"?
Цитата(_hunter @ 7.2.2006, 19:28 Найти цитируемый пост)

а тут другими средствами ( не считая синхронизации ) и не доберешся... делегатов в делфи нету.

но в данном конкретном случае, мне нужно быть уверенным, что процедура выполнится, только тогда, когда поток будет завершён... а сообщение этого не гарантирует.... Насколько я знаю, выполняется OnTerminate в контексте основного(VCL) потока, т.е. тогда, когда поток закончил свою работу, но еще не разрушен... И... насколько я понимаю, проводить синхронизацию в этом событии необязательно..(поправьте меня если я ошибаюсь)
Цитата(_hunter @ 7.2.2006, 19:28 Найти цитируемый пост)

введение потоков так же ( и таким же образом ) усложняет ориентирование.

Увы smile у меня был выбор, либо писать заново, либо модифицировать уже существующий поток... smile


Автор: _hunter 7.2.2006, 20:08
Цитата(Bose @ 7.2.2006, 18:41 Найти цитируемый пост)

т.е. сообщение не могут гулять по системе свободно? в смысле, никто не может послать сообщение м таким номером который воспринимает моя программа в "широковещательном режиме"?

могут конечно и гулять, но это уже параноя -- как ты быдеш знать что никто кроме пользователя не нажмет на кнопку, не откроет файл...
Цитата(Bose @ 7.2.2006, 18:41 Найти цитируемый пост)

но в данном конкретном случае, мне нужно быть уверенным, что процедура выполнится, только тогда, когда поток будет завершён... а сообщение этого не гарантирует....

почему? есть, конечно, вероятность потери сообщения, но она довольно низкая ( и это опять же параноя )
но если есть серьезные основания для волнения по этим пунктам -- пиши менеджер потоков.
Цитата(Bose @ 7.2.2006, 18:41 Найти цитируемый пост)

Насколько я знаю, выполняется OnTerminate в контексте основного(VCL) потока, т.е. тогда, когда поток закончил свою работу, но еще не разрушен... И... насколько я понимаю, проводить синхронизацию в этом событии необязательно..(поправьте меня если я ошибаюсь)

это так, но ты же сам писал "но нельзя её вызывать в OnTerminate."
или я что-то пропустил?

Автор: Bose 8.2.2006, 10:50
Цитата(Bose @ 7.2.2006, 19:41 Найти цитируемый пост)

Насколько я знаю, выполняется OnTerminate в контексте основного(VCL) потока, т.е. тогда, когда поток закончил свою работу, но еще не разрушен...

Цитата(Bose @ 7.2.2006, 19:41 Найти цитируемый пост)

но в данном конкретном случае, мне нужно быть уверенным, что процедура выполнится, только тогда, когда поток будет завершён... а сообщение этого не гарантирует...

я не понимаю, как отсылка сообщения может это гарантировать... Предположим я отсылаю сообщение в обработчике OnTerminate.... Его принимает моя форма и вызывает нужную процедуру. Но я не уверен, что система форма не обработает это сообщение до разрушения потока(выхода из OnTerminate) или я заблуждаюсь?.

Цитата(_hunter @ 7.2.2006, 19:28 Найти цитируемый пост)

поэтому послать сообщение проще, чем заморачиваться с синхронизацией.

Цитата(_hunter @ 7.2.2006, 20:08 Найти цитируемый пост)

это так, но ты же сам писал "но нельзя её вызывать в OnTerminate."
или я что-то пропустил?

про событие OnTerminate я писал к тому, что в этом конкретном случае нет никаких заморочек с синхронизацией smile
вариант с OnTerminate у меня не работает. Я и тему создал, чтобы понять как обойти это событие

Автор: _hunter 8.2.2006, 11:36
ты отсылаеш сообщение последней строкой Execute' а потока. это гарантирует что поток не выполняется ( зачем может понадобится гарантия разрушения?.. )
Цитата(Bose @ 8.2.2006, 09:50 Найти цитируемый пост)

про событие OnTerminate я писал к тому, что в этом конкретном случае нет никаких заморочек с синхронизацией smile
вариант с OnTerminate у меня не работает. Я и тему создал, чтобы понять как обойти это событие

я понял, что я ничего не понял...
рассказывай о проблеме ( и задаче ) с самого начала

Автор: Bose 8.2.2006, 11:55
_hunter проблема была такая:
по окончании действия потока, нужно было вызвать одну процедуру(которая создавала модальную форму, выполняла некоторые длмтельные действия, закрывалась и освобождала форму). Идеальным решением было бы вызвать эту процедуру в событии потока OnTerminate. Но... этот вариант почему-то не работал. Процедура запускалась, форма создавалась, но, действия не выполнялись smile Почему - не известно. Исследование проблемы показало, что эта процедура не работает как надо, только в том случае, если вызвана из OnTerminate. Причины для этого глюка я так и не нашёл. И решил обойти проблему, вызвав процедуру после окончания работы потока.
Точнее после уничтожения, потому что поток работает с БД, и отключается от неё в событии OnTerminate. Процедура, которую мне нужно вызвать, должна работать с этой же БД. Вот и был вопрос как вызвать мою процедуру не из потока, когда поток перестанет существовать.

В качестве решение проблемы я сделал следующее:
поставил на форму выключенный таймер с интервалом 1000 мс.
в событии потока onTerminate этот таймер включается
в событии onTimer таймера запускается моя процедура

Проблема решена, но решение некрасивое. Зато работает smile


Автор: _hunter 8.2.2006, 12:30
а зачем отключаться в OnTerminate? отключайся в потоке.
+ лучше бы проблему додавил а не обходы искал...
++ с таймером код стал гораздо чибальнее и понятнее? ;)

P.S.
отправка сообщения ( в данном случае ) -- идеальный вариант.

P.P.S.
а что будет если паралельно кто-то запустит тяжелый процесс ( и за секунду твой отключиться не успеет )?

Автор: Демо 8.2.2006, 12:31
Bose

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

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

В твоем случае метод решения может быть простой:

Код

type

  TMyThread=class(Tthread)
  ...
  FOnEndThread: Procedure;
  procedure OnEnd;

  public
    constructor Create;
    ...
    property OnEndThread: Procedure read FOnEndThread write FOnEndThread;
    ...
  end;

implementation

constructor TMyThread.Create;
begin
  inherited Create(True);
  FreeOnTerminate := True;
end;

destructor TMyThread.Destroy;
begin
  {
     Здесь выполняем завершающие действия по работе с БД.
  }
  OnEnd;
  inherited Destroy;
end;

procedure TMyThread.OnEnd;
begin
  if Assigned(FOnEndThread) then Synchronize(FOnEndThread);
end;



Вызов:

Код

TForm1=class()
  private
    procedure OnComplete;
...

implementation

procedure TForm1.OnComplete;
begin
  //Выполняем действия по завершению потока
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  with TMyThread.Create do
  begin
      OnEndThread := OnComplete;
      Resume;
  end;


Добавлено @ 12:32

Сорри, процедуру OnComplete надо исключить из методов класса:

Код

implementation    

procedure OnComplete;    
begin    
  //Выполняем действия по завершению потока    
end;    

procedure TForm1.Button1Click(Sender: TObject);    
begin    
  with TMyThread.Create do    
  begin    
      OnEndThread := OnComplete;    
      Resume;    
  end;


PS. Писал прямо здесь, могут быть опечатки.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)