![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Многократный запуск собственного потока [D7, WinXP]
DeScriptor © (2004-07-23 21:27:00)Есть у меня TThread, в котором код Execute выглядит следующим образом:
procedure TResProcessing.Execute();
begin
case JobID of
RP_SCAN: ScanResFile();
RP_EXTR: ExtractFiles();
RP_PACK: PackFiles();
end;
end;
Оказалось, что если я меняю JobID, и снова вызываю метод Resume, ничего больше не происходит (делаю я это после того, как сам поток сообщит основному коду, что он отработал - для этого я целую систему процедур придумал). Я пытался делать Destroy или Free, в той процедуре в главном коде, которую он вызывает, когда сообщает что все сделано, но это приводит к полным висюкам (я вообще не знаю, как убить поток после того, как он сделал свое дело). Я пытался ставить свойство FreeOnTerminate:=true, но это никаких результатов не дало.
А мне нужно, чтобы можно было хоть до посинения нажимать кнопку в главной форме, что приводило бы к выполнению потоком каких-то задач, но с последующей возможностью выполнения им же еще каких-нибудь задач путем нажатия той же самой кнопки. Чего с этим делать - не знаю. И вообще не знаю, убивается ли он при завершении программы. Хелп прочитал на эту тему вдоль и поперек, но ничего толкового так и не достиг.
Создавать для каждого набора задач отдельные экземпляры этого класса, или создавать три разных класса для трех разных наборов задач очень накладно.
А отказаться от использования отдельного потока я не могу, т.к. процессы, которые в нем выполняются, могут затянуться надолго, при этом может возникнуть необходимость прервать их.
Бином Ньютоныч (2004-07-25 17:00:00) [1]Да ничем собсно...так, к слову пришлось:))
DiamondShark (2004-07-25 16:41:00) [2]А, ну да ;)
А чем он лучше WM_QUIT-а?
Бином Ньютоныч (2004-07-25 16:36:00) [3]>DiamondShark © (25.07.04 15:48) [17]
>Такой поток не завершится, пока не отработает какой-нибудь месадж.
Ну дык RP_QUIT на то и вставлен, а?
DiamondShark (2004-07-25 15:48:00) [4]
> Polevi © (24.07.04 22:16) [14]
Такой поток не завершится, пока не отработает какой-нибудь месадж.
procedure TT.Execute;
var
msg:TMsg;
begin
while integer(GetMessage(msg,0,0,0)) > 0 do
case msg.message of
RP_SCAN: ScanResFile();
RP_EXTR: ExtractFiles();
RP_PACK: PackFiles();
RP_QUIT: Terminate;
end;
end;
А для завершения послать WM_QUIT
Polevi (2004-07-25 10:42:00) [5]> [15] Serge_ (25.07.04 00:48)
иногда лучше жевать
Serge_ (2004-07-25 00:48:00) [6]Дак что надо-то, я ваще не понял..
Остановить поток(нить)?
И запустить новый???
али как?
thread.terminate;
Но поток не остановиться сразу, этот метод просто установит флаг Terminated вот его то ты и должен проверять как в методе Execute
так и в процедурах которые вызываются из Execute...
поток завершиться по выходе из Execute...
Если нужно быстрее и менее хлопотно тоды делай TerminateThread(Thread.Handle); твой поток не узнает что ты его залупил...
Polevi (2004-07-24 22:16:00) [7]procedure TT.Execute;
var
msg:TMsg;
begin
while not Terminated do
begin
GetMessage(msg,0,0,0);
case msg.message of
RP_SCAN: ScanResFile();
RP_EXTR: ExtractFiles();
RP_PACK: PackFiles();
RP_QUIT: Terminate;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
PostThreadMessage(T.ThreadId, RP_QUIT, 0, 0);
//последнии 2 параметра будут доступны через msg.wParam и msg.lParam в теле поточной ф-ии
//можете пользоваться
end;
Mim1 (2004-07-24 21:10:00) [8]
> [12] DeScriptor (24.07.04 20:46)
Без suspend поток не будет останавливаться а ьудет вертется вхолостую расходуя ресурсы процессора.
А почему не использовать приведенный пример в полном соответствии один к одному.
DeScriptor (2004-07-24 20:46:00) [9]Ситуевину я разрулил, примерно как предлагал Mim1:
procedure TResProcessing.Execute();
begin
While notTerminated do
if notJobComplete then caseJobID of
RP_SCAN: ScanResFile();
RP_EXTR: ExtractFiles();
RP_PACK: PackFiles();
end;
end;
JobComplete устанавливается в true, когда надо, чтобы поток поработал, как только он заканчивает работу, он устанавливает JobComplete в false, после чего синхронизацией вызывает процедуру из главного потока, которая выполняет дальнейшие действия.
Бином Ньютоныч (2004-07-24 17:22:00) [10]:)))
Теперь въехал:)
Palladin (2004-07-24 16:53:00) [11]:)
А так понятно?
Разделяй и властвуй.
Бином Ньютоныч (2004-07-24 16:48:00) [12]>Palladin © (24.07.04 16:43) [8]
Ни-и-и-и-че не понял:) Можно по-проще, для особо одаренных?
Palladin (2004-07-24 16:43:00) [13]Что есть лучше? Лучшее решение для исполнения? Практически нет, для реализации? Да.
Бином Ньютоныч (2004-07-24 16:19:00) [14]>Palladin © (24.07.04 15:23) [5]
Сомневаюсь, что это будет лучше. Дорогая операция - создание потока, если, конечно, это имеет значение. Имхо, >Polevi © (24.07.04 14:03) [2] оптимально, хотя и не обязательно это должны быть сообщения.
Mim1 (2004-07-24 15:43:00) [15]
> DeScriptor (23.07.04 21:27)
А у меня работает
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TMimThread = class(TThread)
private
procedure SetEndWork;
protected
procedure Execute; override;
public
beepfreq : integer;
published
end;
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
MimThread : TMimThread;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
ThreadWorking : boolean = false;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not (ThreadWorking) then
begin
ThreadWorking := true;
MimThread.beepfreq := -1;
MimThread.resume;
end
end;
{ TMimThread }
procedure TMimThread.Execute;
begin
while not terminated do
begin
MessageBeep(beepfreq);
// windows.MessageBox(0,'1','2',0);
Synchronize(SetEndWork);
suspend;
end;
end;
procedure TMimThread.SetEndWork;
begin
ThreadWorking := false;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
MimThread := TMimThread.Create(true);
MimThread.FreeOnTerminate := true;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
MimThread.terminate;
end;
end.
Palladin (2004-07-24 15:23:00) [16]А еще лучше организовать три разновидности потока на эти разные действия.
DeScriptor (2004-07-24 14:41:00) [17]2Mim1Я пробовал так, как вы советуете - ничего не получается! =( Результат все тот же - полное отсутствие оного.
DeScriptor (2004-07-24 14:37:00) [18]А можно поподробнее про сообщения и их выборку?
Polevi (2004-07-24 14:03:00) [19]а еще лучше организовать в потоке цикл выборки сообщений и управлять им через PostThreadMessage
Mim1 (2004-07-24 08:01:00) [20]Я предлагаю вам такое решение
var
ThreadWorking : boolean = false;
TResProcessing = class(TThread)
Public
JobID:integer;
...
end;
procedure TResProcessing.SetEndWork;
begin
ThreadWorking := false;
end;
> procedure TResProcessing.Execute();
> begin
while not terminated do
begin
> case JobID of
> RP_SCAN: ScanResFile();
> RP_EXTR: ExtractFiles();
> RP_PACK: PackFiles();
> end;
sincronize(SetEndWork);
suspend;
end;
> end;
И в основном потоке
if not (ThreadWorking) then
begin
ThreadWorking := true;
ResProcessing.jobid := 100;
ResProcessing.resume;
end