Текущий архив: 2005.12.25;
Скачать: CL | DM;
Вниз
Приостановка выполнения процедуры, до завершения потока. Найти похожие ветки
← →
Draught (2005-11-30 21:02) [0]Доброго всем времени суток.
Столкнулся с такой ситуацией: при работе приложения для выполнения некоторых операций создается отдельный поток:
HThread:=CreateThread(nil,0,@ThreadFunc,nil,0,ThreadID);
после его выполнения результаты автоматически сохраняются в файл, реализовано это все в одной процедуре, по нажатию на кнопоку старта, выглядит примерно так:
procedure ButtonClick(Sender: TObject);
begin
...
HThread:=CreateThread(nil,0,@ThreadFunc,nil,0,ThreadID);
...
result_savetofile;
...
end;
где result_savetofile- процедура сохраниения результата в соответствующие файлы, в случае неудачи - сохранение соответствующей информации об этом...
Вопрос следующий: после создания отдельного потока требуется каким-либо образом приостанавливать дальнейшее выполнение процедуры, как это можно реализовать?
← →
Draught (2005-11-30 21:12) [1]На самом деле все сводится к простому - каким образом можно выяснить завершился ли поток или все еще выполняется?
← →
Draught (2005-11-30 21:18) [2]Можно использовать как вариант какой-нибудь флаг внутри выполняющегося потока, но может быть есть способ определять состояние потока и без дополнительного флага?
← →
Набережных С. © (2005-12-01 08:48) [3]
> Draught
И нафига тогда поток, если его завершения ждать сразу после создания? Просто делай все внутри самой процедуры.
← →
Draught (2005-12-01 11:22) [4]2Набережных С.
А хотя бы для того, что бы его можно было принудительно завершить не дожидаясь окончания... Так же можно в процессе работы забирать уже готовые данные из потока и передавать их в другое место для обработки другим потоком...
P.S. можно ответ по существу? Личное мнение каждого о коде программы меня не интересует. Мне интересны только советы и корректные ответы на поставленные вопросы...
← →
Reindeer Moss Eater © (2005-12-01 11:32) [5]Так же можно в процессе работы забирать уже готовые данные
Для этого процедура создавшая вторичный поток вовсе не обязана ждать его.
← →
Reindeer Moss Eater © (2005-12-01 11:35) [6]А хотя бы для того, что бы его можно было принудительно завершить не дожидаясь окончания...
Гениально.
Типа что-то похожее не это:
- Ты зачем мастеришь люстру?
- Что бы было светло её делать!
← →
Digitman © (2005-12-01 11:40) [7]
> после создания отдельного потока требуется каким-либо образом
> приостанавливать дальнейшее выполнение процедуры
какой процедуры ?
← →
Reindeer Moss Eater © (2005-12-01 11:42) [8]Как ты собрался гасить поток?
1.Не дожидаясь его завершения?
Принудительно из главного потока, не заботясь о состоянии вторичного?
Abort в главном потоке и неиспользование try/finally сделает то же самое.
Ресурсы и памаять будут утекать столь же эффективно.
2.Прерывать обработку внутри вторичного потока по флагу выставленному главным?
ТО же самое можно сделать в коде основного потока.
Абсолютно то же самое.
← →
Набережных С. © (2005-12-01 12:32) [9]
> Draught (01.12.05 11:22) [4]
> можно ответ по существу? Личное мнение каждого о коде программы
> меня не интересует. Мне интересны только советы и корректные
> ответы на поставленные вопросы...
По существу - теме место в начинающих. А что конкретно тебе интересно, меня не особенно волнует.
← →
Draught (2005-12-01 18:27) [10]>Reindeer Moss Eater ©
>для этого процедура создавшая вторичный поток вовсе не обязана ждать его.
да, все правильно, это может делать любая другая процедура, например при нажатии на другую кнопку или по таймеру...
>Reindeer Moss Eater ©
>Гениально.
>Типа что-то похожее не это:
>- Ты зачем мастеришь люстру?
>- Что бы было светло её делать!
не всегда хватает времени, что бы дождаться окончания процесса, иногда его нужно принудительно прервать, по желанию пользователя или по таймеру...
>Digitman ©
>какой процедуры ?
Процедуру нужно притормозить ту, в которой создается поток (в представленном коде все ясно указано, процедура называется ButtonClick).
>Reindeer Moss Eater ©
>Как ты собрался гасить поток?
да хотя бы так
TerminateThread(HThread,0);
после чего все результаты передать другой процедуре для сохранения или дальнейшей обработки...
В указанном коде есть процедура, в которой есть создание потока и есть процедура, которая вызывается после завершения потока (в любом случае, не зависимо от того, как завершился поток - принудительно или выполнив все необходимые действия).
В потоке используются глобальные переменные(изменяются только внутри потока), к значениям которых можно спокойно обращаться, для получения промежуточных результатов, которые не требуется после завершения потока.
Сейчас все выглядит вот так:
procedure ButtonClick(Sender: TObject);
begin
...
HThread:=CreateThread(nil,0,@ThreadSortList,nil,0,ThreadID);
while HTread_status<>0 do
begin
Sleep(100);
Application.ProcessMessages;
if HTread_status=4 then exit;
end;
...
result_savetofile;
...
end;
На данный момент просто введена дополнительная глобальная переменная, которая имеет разные значения в зависимости от состояния потока(не создан, создан, завершен)
Меня интересует возможность обхода использования этой дополнительной переменной...
← →
Draught (2005-12-01 18:31) [11]млин, с тэгами как-то плохо получилось :(
← →
Leonid Troyanovsky © (2005-12-01 18:44) [12]
> Draught (01.12.05 18:27) [10]
> TerminateThread(HThread,0);
..
> Меня интересует возможность обхода использования этой дополнительной
> переменной...
Снявши голову, по волосам не плачут.
TerminateProcess(GetCurrentProcess, 0) - экономней, да и правильней.
--
Regards, LVT.
← →
Draught (2005-12-01 18:52) [13]> Leonid Troyanovsky ©
> Снявши голову, по волосам не плачут.
> TerminateProcess(GetCurrentProcess, 0) - экономней, да и правильней.
Это шутка такая??? GetCurrentProcess - это я грохну собственный процесс, а не поток, который создал...
TerminateThread(HThread,0); вызывается не из потока, а из другой процедуры - либо пользователь захотел, либо таймер сработал:
procedure TfmMain.Timer1Timer(Sender: TObject);
begin
...
if HTread_status=2 then
begin
TerminateThread(HThread,0);
...
end;
...
end;
← →
Draught (2005-12-01 18:53) [14]Обход переменной, имеется ввиду: HTread_status
← →
Leonid Troyanovsky © (2005-12-01 19:00) [15]
> Draught (01.12.05 18:52) [13]
> > TerminateProcess(GetCurrentProcess, 0) - экономней, да
> и правильней.
> Это шутка такая??? GetCurrentProcess - это я грохну собственный
А зачем создавать невменяемый поток?
Если уж приспичило, то место ему в отдельном процессе,
который при нужде можно и TerminateProcess.
--
Regards, LVT.
← →
Болт (2005-12-01 19:28) [16]WaitForSingleObject
← →
Draught (2005-12-01 19:41) [17]> А зачем создавать невменяемый поток?
Что значит невменяемый поток??? Создаваемый поток делает обработку последовательных данных, критерием окончания работы для потока служат либо отсутсвие данных для обработки, либо желание пользователя прекратить работу, либо таймер (время, затрачиваемое на обработку данных, большее заданного).
> Если уж приспичило, то место ему в отдельном процессе
В таком случае будет сложнее получить данные из отдельного процесса (использование named_pipe мне не подходит, слишком геморно)...
← →
Draught (2005-12-01 19:46) [18]Все, вопрос решен:
Можно вызвать вызвать функцию GetExitCodeThread, проверить, завершен ли поток, идентифицируемый описателем HThread, и, если да, определить его код завершения.
GetExitCodeThread(HThread,pdwExitCode);
Код завершения возвращается в переменной типа DWORD, на которую указывает pdwExitCode. Если поток не завершен на момент вызова GetExitCodeThread, функция записывает в эту переменную идентификатор STILL_ACTIVE (0x103). При успешном вызове функция возвращает TRUE.
GetExitCodeThread(HThread,pdwExitCode);
Sleep(50);
GetExitCodeThread(HThread,pdwExitCode);
while pdwExitCode=STILL_ACTIVE do
begin
Sleep(100);
Application.ProcessMessages;
GetExitCodeThread(HThread,pdwExitCode);
end;
Вот и все, что требовалось... всем спасибо, всем удачи...
← →
Болт (2005-12-01 20:14) [19]
> Вот и все, что требовалось...
Требовалось намного меньше:
HThread:=CreateThread(nil,0,@ThreadFunc,nil,0,ThreadID);
Sleep(500);
while not (WaitForSingleObject(HThread,10)=WAIT_OBJECT_0) do ;
← →
Draught (2005-12-01 20:29) [20]> while not (WaitForSingleObject(HThread,10)=WAIT_OBJECT_0) do; в этом случае главный поток замораживается и нет возможности совершать еще какие-то действия... твой вариант можно переписать так:
Sleep(50);
HThread:=CreateThread(nil,0,@ThreadFunc,nil,0,ThreadID);
Sleep(500);
while not (WaitForSingleObject(HThread,100)=WAIT_OBJECT_0) do
Application.ProcessMessages;
Спасиб за совет, использую твой вариант, доработанный мной :D
← →
Draught (2005-12-01 20:31) [21]первые sleep(50); влезли поошибке...
← →
begin...end © (2005-12-01 20:43) [22]> Draught (30.11.05 21:02)
Поток запускается, выполняет работу, а перед её окончанием, например, посылает сообщение окну (форме) основного потока. В обработчике этого сообщения вызывается процедура сохранения результатов. В этом случае, вроде бы, не придётся периодически проверять, завершился поток или нет -- он сам уведомит об этом кого следует.
Если будет использоваться не CreateThread (которую, кстати, нужно заменить на BeginThread), а TThread, то результаты можно сохранять в обработчике TThread.OnTerminate.
← →
Draught (2005-12-01 21:22) [23]2begin...end
Хорошо, мысль мне ясна, спасибо за совет.
Пошел читать про TThread. :)
Страницы: 1 вся ветка
Текущий архив: 2005.12.25;
Скачать: CL | DM;
Память: 0.53 MB
Время: 0.109 c