![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Есть процедура. Которая может выполняться ну очень долго в силу большого объёма исходного материала. Ну например, какое-нибудь копирование, парсинг, постинг.
Так вот вопрос - как поставить выполнение на паузу, и как остановить. В качестве примера, приведу код процедуры с которой мне вчера помогли - копирование с задержкой: Код:
procedure TForm1.FakeCheck; var i:integer; begin for i := 0 to Memo3.Lines.Count - 1 do begin StatusBar1.Panels.Items[0].Text:= Memo3.Lines[i]; delay(2); //тут задержка в секундах ProgressBar1.Position:=Round(1000 * i/Memo3.Lines.Count-1); end; end; Нужно обрабатывать её тремя кнопками. Запуск, Пауза, Стоп Если с запуском, всё прозрачно, то как её остановить, или прервать - только мысли. Например, использовать конструкцию вроде Form1.Tag := 0; при запуске. По нажатию на кнопку паузы менять значение допустим на единицу, ну а при 2 - останавливать. ![]() |
|
#2
|
||||
|
||||
|
TThread: Create, Suspend, Resume, Terminate
Последний раз редактировалось NumLock, 14.10.2010 в 10:39. |
|
#3
|
||||
|
||||
|
хм...
а если что-нить такое: Код:
for i:=1 to zu do
begin
if action=3 then break;
if action=2 then delay(2);
if action=1 then
begin
выполняем что-то
end;
end;ну и при клике на старт action=1 при клике на стоп action=3 и т.п. |
|
#4
|
|||
|
|||
|
Цитата:
Код:
{Определение класса TMyThread}
type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure DoWork;
procedure Execute; override;
end;
implementation
procedure TMyThread.Execute;
begin
Synchronize(DoWork);
end;
procedure TMyThread.DoWork;
begin
{Сюда, как я понимаю код своей процедуры?}
end;На кнопочки вешаем: TMyThread.Execute; //запуск TMyThread.Suspend; //пауза TMyThread.Resume; //продолжить TMyThread.Terminate; //остановить Я всё правильно понял? 2 friz, спасибо. Буду проверять и более простой вариант. |
|
#5
|
||||
|
||||
|
Код:
procedure TMyThread.Execute; begin DoWork; end; |
|
#6
|
|||
|
|||
|
Цитата:
Теперь ещё более нубский вопрос - по структуре программы. Дело в том, что ковыряюсь я с дельфи - где-то неделю и ещё много пробелов. Цитата:
Нужно размещать после: unit interface uses И перед: type TForm1 = class(TForm) ? Насколько я знаю, type определяет новую категорию переменной или процесса. А чем этот блок type должен завершаться? implementation? Каждый блок или все? |
|
#7
|
||||
|
||||
|
1. не совсем так про Synchronize. как раз наоборот: все потоки могут одновременно обращаться к VCL (в данном случае основной поток и TMyThread) и из-за этого и возникают пролемы. Synchronize для этого и нужен - вызывать метод в основном потоке VCL, что гарантирует безопасное обращение.
2. описание класса в секции interface, реализация в implementation: Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms;
type
TMyThread = class(TThread)
public
constructor Create();
end;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TMyThread }
constructor TMyThread.Create;
begin
inherited Create(False);
end;
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
//
end;
end. |
|
#8
|
|||
|
|||
|
Очень сильно извиняюсь. Пересмотрел кучу примеров, самые толковые из которых:
http://www.codingrus.ru/readarticle.php?article_id=1999 http://www.delphi.int.ru/articles/39/ http://www.codenet.ru/progr/delphi/stat/d_http.php И всё-таки я жутко туплю. Попробую попунктно: 1). Уже создан проект. Начало листинга: Код:
unit vk;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, StdCtrls, ExtDlgs, ComCtrls, CheckLst, Math;
type
TForm1 = class(TForm)
IdHTTP1: TIdHTTP;
PageControl1: TPageControl;
TabSheet1: TTabSheet;
TabSheet2: TTabSheet;
TabSheet3: TTabSheet;
Edit1: TEdit;
Edit2: TEdit;
Label3: TLabel;
Label2: TLabel;
Label1: TLabel;
Button1: TButton;
Memo1: TMemo;
Memo2: TMemo;
Button2: TButton;
OpenDialog1: TOpenDialog;
Button3: TButton;
OpenDialog2: TOpenDialog;
Edit3: TEdit;
Button4: TButton;
Label4: TLabel;
CheckListBox1: TCheckListBox;
Button5: TButton;
Memo3: TMemo;
Label5: TLabel;
Button6: TButton;
Label6: TLabel;
StatusBar1: TStatusBar;
ProgressBar1: TProgressBar;
Button7: TButton;
TabSheet4: TTabSheet;
Edit4: TEdit;
Button8: TButton;
Memo4: TMemo;
Label7: TLabel;
ProgressBar2: TProgressBar;
Label8: TLabel;
Button9: TButton;
Label9: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure Button9Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure Delay (const Seconds: Real);
procedure FakeCheck;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
type
TMyThread = class(TThread)
private
{ Private declarations }
protected
procedure FakeCheck;
procedure Execute; override;
end;Тут FakeCheck эта та самая длительная процедура. По ctrl+shift+c создалось следующее: Код:
{ TMyThread }
procedure TMyThread.Execute;
begin
inherited;
end;
procedure TMyThread.FakeCheck;
begin
end;Добавлю четыре кнопки: btnExecute, btnSuspend, btnResume,btnTerminate Как сделать чтобы: Цитата:
![]() |
|
#9
|
||||
|
||||
|
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TMyThread = class(TThread)
private
str: String;
protected
procedure Execute; override;
procedure Updt;
public
constructor Create;
end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
FMyThread: TMyThread;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TMyThread }
constructor TMyThread.Create;
begin
FreeOnTerminate:=True;
inherited Create(False);
end;
procedure TMyThread.Execute;
begin
str:='begin';
// в Label1 записываем текст в синхронизированом вызове Updt
Synchronize(Updt);
// крутим цикл пока не послан сигнал Terminate
while not Terminated do
begin
Sleep(100);
str:=IntToStr(GetTickCount div 100);
// в Label1 записываем текст в синхронизированом вызове Updt
Synchronize(Updt);
end;
str:='end';
// в Label1 записываем текст в синхронизированом вызове Updt
Synchronize(Updt);
end;
procedure TMyThread.Updt;
begin
// этот метод вызывается в основном потоке VLC
// в Label1 записываем текст
Form1.Label1.Caption:=str;
end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
// создаем поток
if not Assigned(FMyThread) then FMyThread:=TMyThread.Create;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// приостанавливаем выполнение
if Assigned(FMyThread) then FMyThread.Suspend;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
// возобновляем выполнение
if Assigned(FMyThread) then FMyThread.Resume;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
// прерываем выполнение
if Assigned(FMyThread) then FMyThread.Terminate;
end;
end. |
|
#10
|
|||
|
|||
|
Супер! Спасибо!
|
|
#11
|
|||
|
|||
|
Только два момента меня смущают...
Судя по этому FreeOnTerminate:=True; Когда нажата четвёртая кнопка - завершение процесса - идёт зачистка потока, и его можно запускать заново. Однако при попытке запустить снова - кидается ошибкой Неверный дескриптор (6); Отчего сие происходит? Вроде бы ресурсы освобождены... А второй момент касается обращения к компонентам формы из нашей процедуры. Как например, обратится к Memo расположенного на форме. К сожалению, забыл на работе флешку с проектом, и точно не вспомню на что оно ругалось. |
|
#12
|
||||
|
||||
|
1.
Код:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TMyThread = class(TThread)
private
str: String;
protected
procedure Execute; override;
procedure Updt;
public
constructor Create;
destructor Destroy; override;
end;
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private
{ Private declarations }
FMyThread: TMyThread;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TMyThread }
constructor TMyThread.Create;
begin
FreeOnTerminate:=True;
inherited Create(False);
end;
destructor TMyThread.Destroy;
begin
Form1.FMyThread:=nil;
inherited Destroy;
end;
procedure TMyThread.Execute;
begin
str:='begin';
// в Label1 записываем текст в синхронизированом вызове Updt
Synchronize(Updt);
// крутим цикл пока не послан сигнал Terminate
while not Terminated do
begin
Sleep(100);
str:=IntToStr(GetTickCount div 100);
// в Label1 записываем текст в синхронизированом вызове Updt
Synchronize(Updt);
end;
str:='end';
// в Label1 записываем текст в синхронизированом вызове Updt
Synchronize(Updt);
end;
procedure TMyThread.Updt;
begin
// этот метод вызывается в основном потоке VLC
// в Label1 записываем текст
Form1.Label1.Caption:=str;
end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
// создаем поток
if not Assigned(FMyThread) then FMyThread:=TMyThread.Create;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// приостанавливаем выполнение
if Assigned(FMyThread) then FMyThread.Suspend;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
// возобновляем выполнение
if Assigned(FMyThread) then FMyThread.Resume;
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
// прерываем выполнение
if Assigned(FMyThread) then FMyThread.Terminate;
end;
end.2. грубо читать данные из TMemo (и вообще любого другого если пользователь во время работы не изменяет данные) можно и не в Synchronize, но писать лучше в Synchronize. тут проблема еще в отображении может быть. например windows отрисовывает progressbar, когда поток в нем меняет что-то, на экране может смотреться не красиво. |