Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как главному потоку узнать что другой уже закончил работу. [D7, Win95/98, Win2k, WinXP]


Страницы:   1 2

Kolan ©   (2005-07-05 14:31:00) 

Здравствуйте:
 1. Есть структура.
MeasurmentDataRec

 2. Есть тип - указатель на такую структуру. MeasurmentDataRec: PMeasurmentData

 3. Есть поток у которого поле - это указатель на структуру
TMeasurmentThread = class(TThread)
 private
 protected
 public
   FMeasurmentDataRec: PMeasurmentData;
   constructor Create(CreateSuspended: Boolean;
     MeasurmentDataRec: PMeasurmentData);

 4. При создании потока в его поле передается указатель на структуру.
 5. Поток работает с переданной структурой(заполняет её).
 
 6. После того как поток закончил работу надо показать результат пользователю для этого используется процедура
ShowMeasurmentResults(MeasurmentDataRec: PMeasurmentData)
 
Вопрос:
 1. Как запустьть процедуру ShowMeasurmentResultsпо окончании работы потока.

 2. Как убить поток по окончании его работы.


Digitman   (2005-07-06 09:36:00) [1]


> begin...end ©   (06.07.05 09:19) [38]



> как выяснилось, не вс


да, не всегда.

вот реальная ситуация :

ДЛЛ собрана без ран-тайм-пакетов, она самодостаточна, ее код будет использовать код/данные собственных экз-ров юнитов System (где объявлена глоб.переменная MainThreadId) и Classes (где объявлены КС и SyncList)

теперь хост-процесс в доп.трэде грузит эту ДЛЛ, в ходе ее иниц-ции (в контексте загружающеготрэда) произойдет иниц-ия данных юнита System, в т.ч. будет выполнена строка

initialization
..

MainThreadID := GetCurrentThreadID; //текущий трэд - не основной !!! со всеми вытекающими последствиями ...


Fay   (2005-07-06 09:26:00) [2]

2 begin...end ©   (06.07.05 9:19) [38]
Какой ужас. Как-то я по диагонали читал. 8)
Спасибо! Теперь я лучше знаю, за что не люблю всякие TThread-ы. 8)


begin...end   (2005-07-06 09:19:00) [3]

> Fay ©   (06.07.05 9:11) [37]

Насколько я понимаю, метод, подлежащий синхронизации, помещается в глобальный список SyncList, включается Event (SygnalSyncEvent), и метод из списка (в то время, когда у Application очередь сообщений пуста) выполняется внутри Application.Idle (из него вызывается функция Classes.CheckSynchronize) в контексте главного (как выяснилось, не всегда) потока.


Fay   (2005-07-06 09:11:00) [4]

2 begin...end © (06.07.05 9:05) [36]
А в чём ещё? Я не очень внимательно изучал эти Synchronize-ы, т.к. не пользуюсь никогда.
Видимо пропустил что-то важное.


begin...end   (2005-07-06 09:05:00) [5]

> Fay ©   (05.07.05 15:11) [11]
> Крит. секция не меняет коду поток.

Кстати, а причём здесь крит. секция? Смысл Synchronize-то не только в этом.


Digitman   (2005-07-06 09:04:00) [6]


> Какие ресурсы являются для нити своими?


те которые нить создала/заняла в расчете на дальнейшее "монопольное" использование

например, подразумевается, что осн.трэд, создавший некий визуальный VCL-контрол, в дальнейшем (по ходу исполнения программы) ответственен за управление этим контролом, вплоть до его уничтожения, и что ни один другой трэд процесса не вправе обратиться к этому контролу в своем контексте без "ведома" осн.трэда


Fay   (2005-07-06 08:54:00) [7]

2 Digitman © (06.07.05 8:45) [33]
М.б. я туплю, но я что-то не врубаюсь. Какие ресурсы являются для нити своими?
При некотором напряжении я могу представить ресурсы процеса, дальше мысль обрывается.


Digitman   (2005-07-06 08:45:00) [8]


> Fay ©   (05.07.05 17:46) [30]


> почему не всем нитям нужно заходить в CS?


зачем же нити заходить в КС, если по алгоритму она обращается к своимресурсам ?


> Kolan ©   (05.07.05 23:41) [31]



> Как передпть их главному потоку?


например, так :

TMyThread = class(TThread)
..
public
 ExcptObj: TObject;
end;

procedure TMyThread.Execute;
begin
 try
 ..
 except
   ExcptObj := AcquireExceptionObject;
 end;
end;

..

var
E: TObject;
..  
MyThread := TMyThread.Create(параметры);
try
while not Application.Terminated do
case MsgWaitForMultipleObjects(1, MyThread.Handle, False, INFINITE, QS_ALLINPUT) of
WAIT_OBJECT_0: break;
WAIT_OBJECT_0 + 1: Application.ProcessMessages;
finally
E := MyThread.ExcptObj;
MyThread.Free;
end;
if Assigned(E) then
 raise Exception(E)
else
 ShowMeasurmentResults(..);


Fay   (2005-07-06 08:25:00) [9]

2 Kolan ©   (05.07.05 23:41) [31]
Нормально решение, хотя я бы воспользовался бы RegisterWindowMessageвместо WM_USER + 100.


Kolan   (2005-07-05 23:41:00) [10]

Добрый вечер,
Еще пара вопросов:

В процессе заполнения записи возникают ошибки
 
 if RealyOverflow >= 50 then
     raise EConductivityRelayOverflowError{...}


Так как теперь всё это в отдельном потоке то как я понял там они и остаются. Как передпть их главному потоку?

И еще я хочу показать прогресс заполнения записи. Для этого планирую отправлять сообщение с прогрессом.
Это нормально?

PS Сигнализацию конца заполнения сделал с помощью сообщений.

const
 SX_MEASURINGFINISHED = WM_USER + 100;


В конце

PostMessage(FWindowHandle, SX_MEASURINGFINISHED, 0, 0);

В главной форме

procedure TMainForm.SXMeasuringFinished(var Msg: TMessage);
begin
 MeasurmentManager.FinishMeasuring;
 {Грубо говоря MeasurmentThread.Terminate}
 ShowMeasurmentResults(MeasurmentManager.CurrentMeasurment);
end;


Fay   (2005-07-05 17:46:00) [11]

2 Digitman ©   (05.07.05 17:16) [29]

Я и говорю, что не упоминается.
Собственно это мне и кажется странно - почему не всем нитям нужно заходить в CS? Мне такое поведение не кажется очевидным.


Digitman   (2005-07-05 17:16:00) [12]


> Fay ©   (05.07.05 17:10) [28]


а причем здесь крит.секция ?

где в

if GetCurrentThreadID = MainThreadID then
 ASyncRec.FMethod

хоть какое-то упоминание крит.секции ?

никто никуда в дан.случае не "ломится" - тек.трэд, обнаружив совпадение своего Id со значением в глоб.переменной System.MainThreadId, с полным правом вызывает указанный метод в своем же контексте


Fay   (2005-07-05 17:10:00) [13]

Digitman ©   (05.07.05 15:41) [25]
Critical Section. В данном случае "ThreadLock".


Digitman   (2005-07-05 16:24:00) [14]


> Kolan ©   (05.07.05 15:48) [26]


чем [7] не нравится ? там никаких OnTerminate и FreeOnTerminate ..

создал объект и ждешь завершения потока, созданного объектом (после чего с полным правом и уверенностью уничтожаешь объект), в ходе ожидания нормально и оперативно реагируешь на события/сообщения ввода/вывода ..


Kolan   (2005-07-05 15:48:00) [15]


> begin...end ©   (05.07.05 15:33) [21]
> > Kolan ©   (05.07.05 15:29) [19]
>
> > И в конце Execute потока Thread.Terminate.
>
> А смысл?

Перефразирую: Что мне делать когда работа потока уже завершена и осталось вызавать процедуру вывода на экран.

Причём дальше может понадобится опять создать поток итд...

те если поток не удалить(или вот что с ним сделать надо?) то при следующем вызове

MeasurmentThread := TMeasurmentThread.Create(False, MeasurmentDataRec);

MeasurmentThread- перетрется и все и я не смогу его удалить.

Может в конце работы потока посылать сообщение главномуокну. А по появлениии такого сообщения удалять поток и делать вывод на экран?


Digitman   (2005-07-05 15:41:00) [16]


> Fay ©   (05.07.05 15:30) [20]
> Доп. потоки должны ломиться в CS, а основной нет. Он волшебный?


что есть "CS" в дан.случае ?


Digitman   (2005-07-05 15:40:00) [17]


> Если я снова вызову Create. То наверно потеряю ссылку на
> пред. попоток?


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


> Сейчас сделал FreeOnTerminate


в дан.случае, конечно, можно и авторазрушением воспользоваться, поскольку тебе не нужен сам объект, а интересует лишь финальное состояние структуры, переданной по ссылке трэду для обработки

но я бы не рекомендовал


> в конце Execute потока Thread.Terminate. Нормально?


нормально.
но Thread.Terminate в дан.ситуации нужен как корове седло, ибо все что он делает - взводит флаг Thread.Terminated, в определении состоянии которого (как факта, сигнализирующего трэду о необходимости как можно быстрее "закруглиться по хозяйству") по идее д.б. заинтересован сам трэд, который у тебя уже пошел на штатное завершение и ни в каких флагах не нуждается


> Как её выполнить по событию Terminate


ее не надо выполнять.
это защищенный вирт.метод объекта TThread

если он не перекрыт тобой, класс TThread в теле DoTerminate автоматически вызовет (синхронно с MainThreadId) обработчик события OnTerminate, если он назначен тобой на этот момент


begin...end   (2005-07-05 15:36:00) [18]

Добавление к [21]: метод MyObject.MyMethod должен соответствовать типу TNotifyEvent.


Fay   (2005-07-05 15:34:00) [19]

Kolan ©   (05.07.05 15:29) [19]
Можно так.
TMeasurmentThread = class(TThread)
private
 procedure BuBuBu(Sender : TObject);
protected
public
 constructor Create(CreateSuspended: Boolean); override;
 {...}
  procedure DoTerminate;
end;

....
constructor TMeasurmentThread.Create(CreateSuspended: Boolean);
begin
 inherited;
 OnTerminte := BuBuBu;
end;

procedure TMeasurmentThread.BuBuBu(Sender : TObject);
begin
 DoTerminate;
end;

....


begin...end   (2005-07-05 15:33:00) [20]

> Kolan ©   (05.07.05 15:29) [19]

> И в конце Execute потока Thread.Terminate.

А смысл?

> А c этим никак не разбирусь. Можно пример.

MyThread.OnTerminate := MyObject.MyMethod, где MyMethod -- метод объекта MyObject, который требуется выполнить по событию OnTerminate.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо