Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как ждать завершения функции выполняемой в потоке? TThread, WaitFor и т.д. 
:(
    Опции темы
Caduser
Дата 15.1.2007, 07:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 2.10.2006
Где: г. Хабаровск

Репутация: 1
Всего: 1



Есть основная форма, в ней происходит вызов функции которая выполняется долго и естественно блокирует весь интерфейс. Задача: поместить функцию в поток, так чтобы основной интерфейс не блокировался НО ОЖИДАЛ окончания выполнения функции.
В основной форме:
Код

stResult := MyFunc1;
ShowMessage(stResult);

Описание потока и функции:
Код

  TMyThread = class(TThread)
  private
    //
  protected
    procedure Execute; override;
  public
     FstResult: string;
  end;

{ TMyThread }

procedure TMyThread.Execute;
begin
//< тело функции>
// что то долго выполняющееся
 FstResult := 'Результат';
end;

// описание функции
function MyFunc1: string
begin
  MyThread.Resume;
  MyThread.WaitFor;
  result := MyThread.FstResult;
end;

Этот вариант не годится, т.к. WaitFor опять таки все блокирует!
Как ожидать окончание выполнения функции?
(читал много мотериалов но описание подобного применения потоков не нашел)


Это сообщение отредактировал(а) Caduser - 15.1.2007, 07:18
PM MAIL ICQ   Вверх
aktuba
Дата 15.1.2007, 08:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Смышленный
***


Профиль
Группа: Завсегдатай
Сообщений: 1915
Регистрация: 24.4.2006
Где: Планета Земля

Репутация: 16
Всего: 38



Код

stResult := MyFunc1;
while stResult = '' do Application.ProcessMessages;
ShowMessage(stResult);


Это сообщение отредактировал(а) aktuba - 15.1.2007, 08:03


--------------------
user posted image
PM MAIL WWW Skype   Вверх
Caduser
Дата 15.1.2007, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 2.10.2006
Где: г. Хабаровск

Репутация: 1
Всего: 1



Код

while stResult = '' do Application.ProcessMessages;

Действительно работает. Однако не приводит ли этот цикл к дополнительной загрузке процессора (так мне показалось при тестировании)? Может есть какой-нибудь более эффективный способ (пусть даже не простой)?

Это сообщение отредактировал(а) Caduser - 15.1.2007, 10:21
PM MAIL ICQ   Вверх
aktuba
Дата 15.1.2007, 10:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Смышленный
***


Профиль
Группа: Завсегдатай
Сообщений: 1915
Регистрация: 24.4.2006
Где: Планета Земля

Репутация: 16
Всего: 38



Нет, не приводит. Эта строка просто заставляет обрабатывать все сообщения.
Только учти один момент - если функция из потока вернет пустую строку, то код дальше исполняться не будет...

Это сообщение отредактировал(а) aktuba - 15.1.2007, 10:28


--------------------
user posted image
PM MAIL WWW Skype   Вверх
MetalFan
Дата 15.1.2007, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



а не правильнее ли сделать "событие" на завершение работы потока и считать результат?!
просто в приведенном примере смысл отдельного потока теряется абсолютно. могли бы и в главном тоже самое делать.
как лучше сделать:
при старте доп.потока выставляете флаг в главном потоке, что идет обработка данных. по оконачнии работы доп.потока сбрасываете флаг и считывать результат.
ну или вместо флага просто можно выставлять доступность действий/контролов.



--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Snowy
Дата 15.1.2007, 11:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Просто, при завершении работы треда, вызвать нужный метод синхронизацией
PM MAIL   Вверх
aktuba
Дата 15.1.2007, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Смышленный
***


Профиль
Группа: Завсегдатай
Сообщений: 1915
Регистрация: 24.4.2006
Где: Планета Земля

Репутация: 16
Всего: 38



MetalFanSnowy, а какой смысл использовать поток в данной задаче? какой вопрос - такой ответ...


--------------------
user posted image
PM MAIL WWW Skype   Вверх
Snowy
Дата 15.1.2007, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 192
Всего: 484



Код

  TMyThread = class(TThread)
  protected
    procedure Execute; override;
    procedure OnEnd;
  public
     FstResult: string;
  end;

procedure TMyThread.Execute;
begin
//< тело функции>
// что то долго выполняющееся
 FstResult := 'Результат';
  Syncronize(OnEnd);
end;

// описание функции
procedure MyProc1;
begin
  MyThread.Resume;
end;

procedure TMyThread.OnEnd;
begin
  ShowMessage('Результат: ' + FstResult);
end;

PM MAIL   Вверх
Caduser
Дата 16.1.2007, 02:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 2.10.2006
Где: г. Хабаровск

Репутация: 1
Всего: 1



Цитата(MetalFan @ 15.1.2007,  10:52)
просто в приведенном примере смысл отдельного потока теряется абсолютно. могли бы и в главном тоже самое делать.
как лучше сделать:
при старте доп.потока выставляете флаг в главном потоке, что идет обработка данных. по оконачнии работы доп.потока сбрасываете флаг и считывать результат.

Уточняю суть задачи. Тело функции это запрос к базе через DCOM: 
Код

cds1.data := DCOM.AppServer.MyFunc1;

Выполнение этого запроса в главном потоке приводит к полной блокировке интерфейса (Application.ProcessMessages вставлять тут естественно некуда). Единственный выход - поместить DCOM.AppServer.MyFunc1 в отдельный поток, однако выполнение основной программы должно быть приостановлено до завершения выполнения этого потока. 

PM MAIL ICQ   Вверх
MetalFan
Дата 16.1.2007, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



Цитата(Caduser @  16.1.2007,  02:25 Найти цитируемый пост)
выполнение основной программы должно быть приостановлено

так, тогда зачем еще один поток? у тебя и так "приостановится" главный поток, пока не выполнится данная функция ;)

наверное ты имел ввиду не полную "приостановку", а просто блокировку части GUI до завершения операции?
тогда правильнее, имхо, сделать нотфикацию форме после завершения выполнения функции в трэде... а перед созданием оного блокируй часть контролов.
это будет правильнее, чем крутиться в цикле с ProcessMessages, проверяя состояние доп.потока
в общем смотри, пример уже дали ;)

Это сообщение отредактировал(а) MetalFan - 16.1.2007, 09:45


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
aktuba
Дата 16.1.2007, 09:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Смышленный
***


Профиль
Группа: Завсегдатай
Сообщений: 1915
Регистрация: 24.4.2006
Где: Планета Земля

Репутация: 16
Всего: 38



MetalFan, ты не понял. Ему наоборот надо НЕ блокировать GUI, но ждать результата функции.
Я бы тоже не выносил в отдельный поток. Просто в выполняемой функции, занимающей долгое время, добавил ProcessMessages...


--------------------
user posted image
PM MAIL WWW Skype   Вверх
MetalFan
Дата 16.1.2007, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 62
Всего: 128



aktuba, это ты не понял. НЕКУДА ему добавлять ProcessMesages при выполнении функции в главном потоке)


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
CatATonik
Дата 16.1.2007, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 95
Регистрация: 12.1.2007
Где: Москва

Репутация: 6
Всего: 8



Вот так, и процессор не грузится, только обязательно в конце нужно послать приложению какое либо сообщение (не обязательно WM_ACTIVATEAPP):

Код

procedure TMyForm.MyLongTimeProc;
begin
  stResult := '';
  MyThread := TMyThread.Create(False);
  while (stResult = '') and not Application.Terminated do
    Application.HandleMessage;
end;

procedure TMyThread.Execute;
begin
  try
    cds1.data := DCOM.AppServer.MyFunc1;
    stResult := 'Результат';
  finally
    SendMessage(Application.Handle, WM_ACTIVATEAPP, 1, 0);
  end;
end;

PM MAIL   Вверх
Caduser
Дата 22.1.2007, 04:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 2.10.2006
Где: г. Хабаровск

Репутация: 1
Всего: 1



Цитата(CatATonik @  16.1.2007,  10:53 Найти цитируемый пост)
Вот так, и процессор не грузится, только обязательно в конце нужно послать приложению какое либо сообщение (не обязательно WM_ACTIVATEAPP)

Отличное решение, все работает, спасибо.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0890 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.