Форум: "Основная";
Текущий архив: 2004.08.08;
Скачать: [xml.tar.bz2];
ВнизМногократный запуск собственного потока Найти похожие ветки
← →
DeScriptor (2004-07-23 21:27) [0]Есть у меня 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, но это никаких результатов не дало.
А мне нужно, чтобы можно было хоть до посинения нажимать кнопку в главной форме, что приводило бы к выполнению потоком каких-то задач, но с последующей возможностью выполнения им же еще каких-нибудь задач путем нажатия той же самой кнопки. Чего с этим делать - не знаю. И вообще не знаю, убивается ли он при завершении программы. Хелп прочитал на эту тему вдоль и поперек, но ничего толкового так и не достиг.
Создавать для каждого набора задач отдельные экземпляры этого класса, или создавать три разных класса для трех разных наборов задач очень накладно.
А отказаться от использования отдельного потока я не могу, т.к. процессы, которые в нем выполняются, могут затянуться надолго, при этом может возникнуть необходимость прервать их.
← →
Mim1 © (2004-07-24 08:01) [1]Я предлагаю вам такое решение
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
← →
Polevi © (2004-07-24 14:03) [2]а еще лучше организовать в потоке цикл выборки сообщений и управлять им через PostThreadMessage
← →
DeScriptor (2004-07-24 14:37) [3]А можно поподробнее про сообщения и их выборку?
← →
DeScriptor (2004-07-24 14:41) [4]2Mim1 Я пробовал так, как вы советуете - ничего не получается! =( Результат все тот же - полное отсутствие оного.
← →
Palladin © (2004-07-24 15:23) [5]А еще лучше организовать три разновидности потока на эти разные действия.
← →
Mim1 © (2004-07-24 15:43) [6]
> 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.
← →
Бином Ньютоныч (2004-07-24 16:19) [7]>Palladin © (24.07.04 15:23) [5]
Сомневаюсь, что это будет лучше. Дорогая операция - создание потока, если, конечно, это имеет значение. Имхо, >Polevi © (24.07.04 14:03) [2] оптимально, хотя и не обязательно это должны быть сообщения.
← →
Palladin © (2004-07-24 16:43) [8]Что есть лучше? Лучшее решение для исполнения? Практически нет, для реализации? Да.
← →
Бином Ньютоныч (2004-07-24 16:48) [9]>Palladin © (24.07.04 16:43) [8]
Ни-и-и-и-че не понял:) Можно по-проще, для особо одаренных?
← →
Palladin © (2004-07-24 16:53) [10]:)
А так понятно?
Разделяй и властвуй.
← →
Бином Ньютоныч (2004-07-24 17:22) [11]:)))
Теперь въехал:)
← →
DeScriptor (2004-07-24 20:46) [12]Ситуевину я разрулил, примерно как предлагал Mim1:
procedure TResProcessing.Execute();
begin
While not Terminated do
if not JobComplete then case JobID of
RP_SCAN: ScanResFile();
RP_EXTR: ExtractFiles();
RP_PACK: PackFiles();
end;
end;
JobComplete устанавливается в true, когда надо, чтобы поток поработал, как только он заканчивает работу, он устанавливает JobComplete в false, после чего синхронизацией вызывает процедуру из главного потока, которая выполняет дальнейшие действия.
← →
Mim1 © (2004-07-24 21:10) [13]
> [12] DeScriptor (24.07.04 20:46)
Без suspend поток не будет останавливаться а ьудет вертется вхолостую расходуя ресурсы процессора.
А почему не использовать приведенный пример в полном соответствии один к одному.
← →
Polevi © (2004-07-24 22:16) [14]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;
← →
Serge_ (2004-07-25 00:48) [15]Дак что надо-то, я ваще не понял..
Остановить поток(нить)?
И запустить новый???
али как?
thread.terminate;
Но поток не остановиться сразу, этот метод просто установит флаг Terminated вот его то ты и должен проверять как в методе Execute
так и в процедурах которые вызываются из Execute...
поток завершиться по выходе из Execute...
Если нужно быстрее и менее хлопотно тоды делай TerminateThread(Thread.Handle); твой поток не узнает что ты его залупил...
← →
Polevi © (2004-07-25 10:42) [16]> [15] Serge_ (25.07.04 00:48)
иногда лучше жевать
← →
DiamondShark © (2004-07-25 15:48) [17]
> 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
← →
Бином Ньютоныч (2004-07-25 16:36) [18]>DiamondShark © (25.07.04 15:48) [17]
>Такой поток не завершится, пока не отработает какой-нибудь месадж.
Ну дык RP_QUIT на то и вставлен, а?
← →
DiamondShark © (2004-07-25 16:41) [19]А, ну да ;)
А чем он лучше WM_QUIT-а?
← →
Бином Ньютоныч (2004-07-25 17:00) [20]Да ничем собсно...так, к слову пришлось:))
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.08.08;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.038 c