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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 31.07.2011, 22:20   #1
Delphi_ProGer
Форумчанин
 
Регистрация: 30.10.2010
Сообщений: 524
По умолчанию Потоки(TThread). Возврат значений функции.

Здраствуйте! Проблема такова: я имею класс, в котором есть много ф-й и результат ф-й заноситься в глобальную переменную. Когда я исполняю поток, то немогу взнать когда он закончит свою работу(или точнее не знаю как это проверить).
Вопрос такой: как это сделать?

Пример кода:
Код:
var MyThread: TMyThread;
Globalresult : boolean;
...
TMyThread.Execute;
begin
case ThreadMethod of
m1: ...;
m2: ...;
end;
end;
...

Код:
begin
MyThread.Resume;
ThreadMethod:=m1;
if GlobalResult = true then ...  // вот здесь проверяеться значение, но поток еще виполнил эту ф-ю
end;
Извините, если кое-что непонятно.
Delphi_ProGer вне форума Ответить с цитированием
Старый 31.07.2011, 22:46   #2
mss
Заблокирован
 
Регистрация: 27.05.2010
Сообщений: 1,099
По умолчанию

Цитата:
немогу взнать когда он закончит свою работу(или точнее не знаю как это проверить)
Если завершением работы доп.потока заинтересован осн.поток VCL-приложения, то для этого Борланд предусмотрела событие OnTerminate - его обработчик синхронизирован с осн.потоком, т.е. будет исполнен в контексте осн.потока.
Формально OnTerminate не есть факт завершения собственно поточной ф-ции, но это событие возбуждается после завершения работы метода TThread.Execute

Последний раз редактировалось mss; 31.07.2011 в 22:48.
mss вне форума Ответить с цитированием
Старый 31.07.2011, 22:47   #3
Delphi_ProGer
Форумчанин
 
Регистрация: 30.10.2010
Сообщений: 524
По умолчанию

Цитата:
Сообщение от mss Посмотреть сообщение
Если завершением работы доп.потока заинтересован осн.поток VCL-приложения, то для этого Борланд предусмотрела событие OnTerminate - его обработчик синхронизирован с осн.потоком, т.е. будет исполнен в контексте осн.потока
А если об'єкт потока не будет уничтожаться а только Suspend?
Delphi_ProGer вне форума Ответить с цитированием
Старый 31.07.2011, 23:08   #4
mss
Заблокирован
 
Регистрация: 27.05.2010
Сообщений: 1,099
По умолчанию

Цитата:
А если об'єкт потока не будет уничтожаться а только Suspend?
Тогда следует реализовать собственные способы синхронизации.
Это м.б. и штатный Synchronize (сфера его использования довольно специфична и ограничена) и иные объекты синхр-ции, начиная с CriticalSection и заканчивая глобальными объектами (Event, Mutex, Semaphore).

Для гурманов и особо умудренных ОС предоставляет еще и объекты-файберы.
mss вне форума Ответить с цитированием
Старый 01.08.2011, 12:44   #5
cargo29
Форумчанин
 
Регистрация: 13.12.2010
Сообщений: 603
По умолчанию

Поток TThread считается завершенным, когда завершается выполнение его мето
да Execute(). В этот момент вызывается стандартная процедура Delphi End-
Thread(), которая, в свою очередь, вызывает функцию API Win32 ExitThread().
Данная функция должным образом освобождает стек потока и сам объект потока API.
По завершении ее работы поток перестает существовать и все использованные им ре
сурсы будут освобождены.

Код:
procedure TTestThread.Execute;
var
i: integer;
begin
FreeOnTerminate := True;
for i := 1 to 2000000 do begin
if Terminated then Break;
inc(Answer, Round(Abs(Sin(Sqrt(i)))));
end;
end;
cargo29 вне форума Ответить с цитированием
Старый 01.08.2011, 13:44   #6
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

Код:
MyThread.Resume;
ThreadMethod:=m1;
замечательно, сначала запускаем поток, а потом уже говорим, что ему делать ) Строчки надо переставить местами.

Вобще, логика должна быть примерно такая:

1) инициализируем поток, сбрасываем событие (ResetEvent)

2) запускаем поток, по завершению работы он должен установить событие (SetEvent) в сигнальное состояние

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

Вобще, идея с suspend/resume не очень, имхо. Проще действительно OnTerminate использовать.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Старый 01.08.2011, 18:47   #7
Delphi_ProGer
Форумчанин
 
Регистрация: 30.10.2010
Сообщений: 524
По умолчанию

Цитата:
Сообщение от veniside Посмотреть сообщение
Код:
MyThread.Resume;
ThreadMethod:=m1;
замечательно, сначала запускаем поток, а потом уже говорим, что ему делать ) Строчки надо переставить местами.

это просто сам на скорую написал код, т.е. приблизительный пример) Так что ошыбки могли быть, но дело не в этом.

А так, спасибо всем за советы!
Delphi_ProGer вне форума Ответить с цитированием
Старый 07.08.2011, 13:07   #8
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

щас вот подумал, вместо suspend/resume, которые уже давно deprecated, на порядок лучше использовать такую схему: есть два события, одно сигнализирует о том, что для потока есть новая работа (EvNewJob), и второе, говорящее о том, что поток с работой справился (EvJobDone). Тогда схема будет такая:

дополнительный поток:

Код:
  1) ждёт WaitForSingleObject(EvNewJob), скажем, 10 секунд
  2) если дождался и not Terminated, то:
    2.1) выполняет работу
    2.2) выставляет EvJobDone в сигнальное состояние
  3) если поток не просят завершиться (not Terminated) то опять на шаг 1)
основной поток:

Код:
 -- запуск программы:
  0) сбрасываем EvNewJob, создаём доп. поток

 -- есть новая работа:
  1) сбрасываем EvJobDone
  2) заполняем поля потока, чтобы он знал, над чем работать, когда проснётся
  3) устанавливаем EvNewJob
  4) периодически проверяем EvJobDone, если установлено, считываем результаты работы из потока.
  5) по приходу новой работы, идём на шаг 1)

 -- выход из программы:
  6) просим поток завершиться (вызываем Terminate()) и устанавливаем EvNewJob, чтобы поток проснулся и завершился нормальным образом

У EvNewJob желательно ManualReset = False, или не забывать сбрасывать самому.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."

Последний раз редактировалось veniside; 07.08.2011 в 13:15.
veniside вне форума Ответить с цитированием
Старый 07.08.2011, 17:04   #9
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
которые уже давно deprecated
кхм, с чего это они устарели?

или вы имели в виду что подход через их использование устарел?(тогда согласен)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 07.08.2011, 18:46   #10
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

из исходников Classes.pas из Delphi 2010:

Код:
    procedure Resume; deprecated;
    procedure Suspend; deprecated;
ну ок, не так давно. Но давно пора )
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."
veniside вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Возврат значений из DLL в реальном времени Alter Общие вопросы Delphi 5 21.06.2011 19:43
Возврат значения из класса TThread Alter Общие вопросы Delphi 1 27.12.2010 21:48
Мини бэйсик:объявление функции, вызов функции , возврат. AL_LORD Помощь студентам 2 14.10.2010 17:48
возврат значений - дерево ArniLand Общие вопросы по Java, Java SE, Kotlin 3 23.09.2010 11:17
Возврат массива значений в функцию main. sadf Общие вопросы C/C++ 5 03.03.2010 21:32