-
Как нужно правильно, не дожидаясь окончания выполнения Execute, прервать выполнение кода потока и освободится - NewThread.Free;? TNewThread = class(TThread)
private
protected
procedure Execute; override;
end;
var
Form1: TForm1;
implementation
procedure TNewThread.Execute;
begin
while true do ;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
NewThread: TNewThread;
begin
NewThread:=TNewThread.Create(true);
NewThread.FreeOnTerminate:=true;
NewThread.Priority:=tpLower;
NewThread.Resume;
end;
-
procedure TNewThread.Execute; begin while not Terminated do {ничего не делаем}; end;
procedure TForm1.Button1Click(Sender: TObject); var NewThread: TNewThread; begin NewThread := TNewThread.Create(true); NewThread.FreeOnTerminate := true; NewThread.Priority := tpLower; NewThread.Resume; Sleep(2000); // Дадим потоку NewThread поработать 2 секунды NewThread.Terminate; // а затем прервем его работу. end;
-
> Sleep(2000); // Дадим потоку NewThread поработать 2 секунды
А без этого?
-
Пояснение.
Вызов метода Terminate не прерывает работу потока NewThread немедленно, а только выставляет его флаг завершения (свойство Terminated).
В методе Execute этот флаг проверяется и если он выставлен, то происходит выход из метода Execute, что приводит к реальному завершению потока.
-
> fics © (09.04.17 19:00) [2]
> А без этого?
Нет проблем. Поток NewThread стартует (т.к. вызван метод Resume) и тут же завершится (т.к. Terminated = true).
-
Ясно. Вот, к примеру, если при новом нажатии клавиши вызов от предыдущего нажатия еще не доработал, то екстренно прервать его и начать выполнение сначала вообще не получится? procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
NewThread.Еxecute;
end; Посему получается, что будет сделать это вообще нереально.
-
> Нет проблем. Поток NewThread стартует (т.к. вызван метод > Resume) и тут же завершится (т.к. Terminated = true).
ну так не устраивает, нужно при необходимости быстро оборвать поток и начать заново. Чтобы это было не заметно в FormKeyPress при вводе текста в редактор
-
Начать новое выполнение того же самого потока без его завершения - не получится. А прямой вызов NewThread.Еxecute вообще не запускает новый поток, а только выполняет метод Execute в вызвавшемпотоке.
-
fics © (09.04.17 19:16) [5]
Было бы гораздо легче и полезнее, если бы была озвучена реальная задача, которую надо решить.
-
Что же делать:) Не в отдельном потоке тоже не получиься выходить из фунции так вызовы все равно в стеке
-
> fics © (09.04.17 19:41) [9] > Что же делать:)
То, что сказал Игорь - озвучить реальную задачу.
Причем именно саму реальную задачу, а не предполагаемые Вами способы ее решения. Способы найдем вместе.
-
> Игорь Шевченко © (09.04.17 19:38) [8] > > fics © (09.04.17 19:16) [5] > > Было бы гораздо легче и полезнее, если бы была озвучена > реальная задача, которую надо решить.
Озвучиваю. Самописный редактор с подсветкой строк, комментариев итд , где при вводе нового символа нужно запускать весь текст на анализ. При новом нажатии клавиши предыдущее сканирование становиться бессмысленным. А сканирования большого файла может длится секунды.
-
fics © (09.04.17 19:54) [11]
Найди исходники Far Colorer - он это делает мгновенно.
-
> Найди исходники Far Colorer - он это делает мгновенно.
Файл в несколько сот тысяч строк он мгновенно не обработает. И при быстром вводе пересканировка наверняка запускается заново. Ну буду копать, делать нечего.
-
Подсветка (рисование) происходит непосредственно по ходу парсинга?
-
ну так не устраивает, нужно при необходимости быстро оборвать поток и начать заново.
не нужно.
старый экземпляр - такой же точно (не хуже) чем тот который ты хочешь запустить. а тот который ты хочешь запустить - ничем не лучше того, который уже запущен.
все что ты тут делаешь (вместо полезного) - насилуешь систему, зачем-то стартуя и останавливая свои потоки.
-
> при вводе нового символа нужно запускать весь текст на анализ
вот есть такой текст: тут тыща строк
<wrap>ща мы тут введем новый символ</wrap>
и тут тыща строк зачем запускать весь текст на анализ, ведь по сути, ничего не изменилось? другой вариант:
<wrap>
тут тыща строк
<superwrap>ща мы тут испортим закрывающий тег</superwrap>
и тут тыща строк
<superwrap>
и тут тыща строк
</superwrap>
</wrap>
и даже в этом случае изменилась лишь координата </superwrap>, анализировать весь текст - бессмысленно и беспощадно
-
> fics © (09.04.17 19:54) [11]
> где при вводе нового символа нужно запускать весь текст на анализ.
Можно хоть в одном потоке всё организовать. Обработку запускать при срабатывании таймера простоя. Только саму обработку вести небольшими порциями, дабы быстро реагировать на возобновление ввода. See also https://rsdn.org/forum/delphi/942829.1-- Regards, LVT.
-
> И при быстром вводе пересканировка наверняка запускается заново. т.е. ты не нашел, не попробовал, не знаешь наверняка, а просто предполагаешь?
потоков вообще не нужно, берите пример с дельфевского редактора, там перерисовывается только видимая часть в обычном онпаинт... работает моментально, даже если по каждому клику перерисовывает все окно, хотя на самом деле не знаю как там внутри, может только введенную букву/примыкающее слово.
Far Colorer скорее всего организован также, а значит количество текста не влияет на скорость "покраски".
-
> Подсветка (рисование) происходит непосредственно по ходу > парсинга?
нет - строится массив состояний.
-
> kilkennycat © (10.04.17 09:16) [16]
Так у меня полной пересканировки и нет при вводе обычных символов. Она запускается только при вводе кавычек и комментария и то с места их ввода и до конца
-
> Leonid Troyanovsky © (10.04.17 09:50) [17]
> sniknik © (10.04.17 10:10) [18]
Буду колдовать с таймером. Было что-то типа: Scan;
begin
n := 1;
while n <> Length(Text) do begin
inc(n)
end;
end; А теперь что-то из этого мудрить нужно
-
while n <> Length(Text) do begin
if ( fNewText ) then Break;
inc(n)
end;
-
> NoUser © (10.04.17 11:48) [22] > > while n <> Length(Text) do begin > if ( fNewText ) then Break; > {-----} > inc(n) > end;
Ну без задержки таймером все равно не получиться, так как и fNewText и вызов Scan идут с одной точки, оборвать так конечно можно, но нужно как-то ждать выхода из функции. Без таймера тут не обойтись, так как:
unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Label1: TLabel; Label2: TLabel; procedure FormKeyPress(Sender: TObject; var Key: Char); procedure FormActivate(Sender: TObject); private { Private declarations } public SyspendFlag: Boolean; function Scan: Boolean; end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormActivate(Sender: TObject); begin SyspendFlag := False; Scan; end;
function TForm1.Scan: Boolean; var n: Integer; begin n := 0; while n < 214748364 do begin if SyspendFlag then begin Label2.Caption := IntToStr(n); {тут всегда будет ноль} Break; end; Inc(n); Application.ProcessMessages; end;
SyspendFlag := False; end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin SyspendFlag := True; Label1.Caption := Key; Scan; end;
-
type TForm1 = class(TForm) Memo1: TMemo; Label1: TLabel; procedure Memo1KeyPress(Sender: TObject; var Key: Char); procedure FormClose(Sender: TObject; var Action: TCloseAction); private fInScan :Boolean; fReScan :Boolean; fBrScan :Boolean; function Scan: Boolean; procedure WmUser100(var Msg:TMessage); message WM_USER+1; end; var Form1: TForm1;
implementation
{$R *.dfm}
function TForm1.Scan: Boolean; var n: Integer; begin fInScan := True; fBrScan := False; n := 0; while n < 214748364 do begin if (fReScan) then begin fReScan := False; Memo1.Lines.Add(IntToStr(n)); n := 0; end; if (fBrScan) then Break; Inc(n); Application.ProcessMessages; end; fInScan := False; end;
procedure TForm1.WmUser100(var Msg: TMessage); begin if ( fInScan ) then fReScan := True else Scan; end;
procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char); begin PostMessage(Handle, WM_USER+1,0,0); end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin fBrScan := True; end;
-
> NoUser © (10.04.17 17:01) [24]
Ну концептуально примерно правильно, но где fBrScan становится истинным, кроме как при закрытии формы? Ведь нужно же обрывать цикл при новом вводе, а выход только по if (fBrScan) then Break; И это не правильная логика, если Scan будет успевать дорабатывать до конца, то нового Скана не будет procedure TForm1.WmUser100(var Msg: TMessage); begin if ( fInScan ) then fReScan := True else Scan; end;
-
точнее при первом нажатии клавиши мы оборвем предыдущий цикл, а новый не начнем.
правильнее наверное будет так: (но только наверное ) нужно потестировать
function TForm1.Scan: Boolean; var n: Integer; begin fInScan := True; n := 0; while n < 214748364 do begin if (fReScan) then begin fReScan := False; Scan; {вызов после прекращения предыдущего} Break; end; Inc(n); Application.ProcessMessages; end;
fInScan := False; end;
-
> Ведь нужно же обрывать цикл при новом вводе,
Зачем обрывать если можно сказать сканируй заново ? (ну, и подсунь данные, которые нужны для нового скана)
А обрывать, это если юзеру уже нужно новый документ или винда пошла обновляться. ))
> если Scan будет успевать дорабатывать до конца, то нового Скана не будет
отлично, значит успели просканить до ввода нового символа - как и задумано!
|