Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.07.09;
Скачать: CL | DM;

Вниз

Как правильно реализовать эффект   Найти похожие ветки [Останов/Продолжить]

 
Schooler   (2006-05-22 16:13) [0]

На форме :
 TreeView1   :TTreeView;
 btnExecute  :TButton;
 btnContinue :TButton;

Прохожу по TreeView1 последовательно в цикле (кнопка btnExecute):

procedure TForm1.btnExecuteClick(Sender:TObject);
begin
 for i:= to to TreeView1.Items.Count-1 do  
 begin
   if TreeView1.Items[i].HasChildren
   then
     begin
         // Некоторые действия
         // ...
        // Конец   Некоторые действия
     
        // Вот здесь нужно сделать ActiveControl := btnContinue
        // и приостановить выполнение Цикла:
        // при нажатии btnContinue продолжить Цикл
     end;
  end;
end;


Как правильно такие вещи делать ? Это TThread"ы ?


 
StriderMan ©   (2006-05-22 16:29) [1]

можно запомнить переменную i и потом с нее продолжить...


 
Сергей М. ©   (2006-05-22 16:31) [2]


> Это TThread"ы ?


Где ?


 
Schooler   (2006-05-22 16:42) [3]

To StriderMan ©   (22.05.06 16:29) [1]

Была такая идея и у меня.
Мне, кажется, не подойдет такой вариант: т.е. я не хочу покидать тело процедуры, там ряд локальных переменных, которые я потеряю (здесь упрощенный код).

To Сергей М. ©   (22.05.06 16:31) [2]

Что если обработчик кнопки завернуть в метод MyThread.Execute?


> Где ?


Я что, принипиально не в том направлении иду?


 
Сергей М. ©   (2006-05-22 16:45) [4]


> Schooler   (22.05.06 16:42) [3]


> обработчик кнопки завернуть в метод MyThread.Execute


Зачем ?


> Я что, принипиально не в том направлении иду?


Очень на то похоже ...


 
StriderMan ©   (2006-05-22 16:52) [5]


> т.е. я не хочу покидать тело процедуры


может показать модальное окошко с вопросом типа "продолжить?"

есть еще такой вариант (мне самому не нравится, но на ум пришел):
заводишь в private"е формы флаг fContinue типа boolean. он выставляется в true обработчиком кнопки btnContinue.
а далее в тело твоего цикла впихнуть код

while not fContinue do
 Application.ProcessMessages;
fContinue := false;


но стоит 33 раза подумать преждем чем так делать. Ведь кроме btnContinue пользователь может нажать и другие кнопки, и что произойдет тогда, одному ежу ведомо


> там ряд локальных переменных, которые я потеряю (здесь упрощенный
> код)

можно завести под них record и поместить в Private класса формы


 
Schooler   (2006-05-22 16:52) [6]

To Сергей М. ©   (22.05.06 16:45) [4]

1. Ваш Вариант решения?

2. И, если не сложно, почему
> Очень на то похоже ...
?


 
Schooler   (2006-05-22 16:58) [7]

To StriderMan ©   (22.05.06 16:52) [5]


> может показать модальное окошко с вопросом типа "продолжить?
> "

В том то и дело, изначально было ShowMessage

Об этом

> btnContinue пользователь может нажать и другие кнопки

естественно, нужно позаботиться! :

...
btnOther1.Enabled := false;
...
btnOtherN.Enabled := false;
...


 
StriderMan ©   (2006-05-22 17:12) [8]


> естественно, нужно позаботиться! :

ну если сделать все аккуратно, то мой вариант подходит. Вообще нужно задисаблить все кроме это кнопки

но все равно как-то не очень...

о! еще мысль пришла!

завести класс типа TMyTreeProcess. в нем будут описаны все переменные из процедуры и сама процедура
и добавить методы типа .Pause и .Continue;

дальше объяснять?


 
Сергей М. ©   (2006-05-23 08:04) [9]


> Schooler   (22.05.06 16:52) [6]


Сначала уточни, может ли измениться содержимое списка узлов в период между паузой и возобновлением ..


 
Schooler   (2006-05-29 11:34) [10]

To Сергей М. © & All

Извиняйте, был в командировке.
Вот по поводу Thread-ов:


unit Unit2;

interface

uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls, ComCtrls;

type

 TContinueThread = class(TThread)
 private
   Current:integer;
   FCount: integer;
   procedure SetCount(const Value: integer);
 public
   property Count:integer read FCount write SetCount;
   procedure Execute;override;
   procedure WaitForContinue;
 end;

 TForm1 = class(TForm)
   TreeView1: TTreeView;
   btnExecute: TButton;
   btnAbort: TButton;
   procedure FormActivate(Sender: TObject);
   procedure btnExecuteClick(Sender: TObject);
   procedure btnAbortClick(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 ContinueThread:TContinueThread;

implementation

{$R *.DFM}

procedure TForm1.btnExecuteClick(Sender: TObject);
Var
 k:integer;
begin

if ContinueThread = nil
then
  begin
    btnExecute.Caption  := "Continue";
    btnAbort.Enabled := true;

    ContinueThread          := TContinueThread.Create(TRUE);
    ContinueThread.Count    := TreeView1.Items.Count;
    ContinueThread.Priority := tpNormal;
    ContinueThread.Resume;
  end
else
  begin
    if ContinueThread.Terminated
    then
      begin
        Form1.btnAbort.Enabled := false;
        btnExecute.Caption  := "Execute";
        ContinueThread.Destroy;
        ContinueThread := nil;
        btnAbort.Enabled := false;
        TreeView1.Selected := TreeView1.Items[0];
      end
    else ContinueThread.Resume;
  end;
end;

procedure TForm1.btnAbortClick(Sender: TObject);
begin
if ContinueThread<>nil
then
  begin
    btnExecute.Caption  := "Execute";
    ContinueThread.Destroy;
    ContinueThread := nil;
    btnAbort.Enabled := false;
   TreeView1.Selected := TreeView1.Items[0];
  end;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
TreeView1.FullExpand;
btnAbort.Enabled := false;
end;

{ TCircleThread }

procedure TContinueThread.Execute;
Var
i:integer;
begin
 for i:=0 to Count-1 Do
 begin
   Current := i;
   Synchronize(WaitForContinue);
 end;
 Terminate;
end;

procedure TContinueThread.WaitForContinue;
begin
if Form1.TreeView1.Items[Current].HasChildren
then
  begin
    Form1.TreeView1.Selected := Form1.TreeView1.Items[Current];
    Form1.ActiveControl:=Form1.btnExecute;
    Suspend;
  end
else Resume;
end;

procedure TContinueThread.SetCount(const Value: integer);
begin
 FCount := Value;
end;

end.


object Form1: TForm1
 Left = 178
 Top = 103
 Width = 456
 Height = 467
 Caption = "Form1"
 Color = clBtnFace
 Font.Charset = DEFAULT_CHARSET
 Font.Color = clWindowText
 Font.Height = -11
 Font.Name = "MS Sans Serif"
 Font.Style = []
 OldCreateOrder = False
 OnActivate = FormActivate
 PixelsPerInch = 96
 TextHeight = 13
 object TreeView1: TTreeView
   Left = 0
   Top = 0
   Width = 448
   Height = 397
   Align = alTop
   HideSelection = False
   Indent = 19
   TabOrder = 0
   Items.Data = {
     010000001D0000000000000000000000FFFFFFFFFFFFFFFF0000000006000000
     04526F6F741D0000000000000000000000FFFFFFFFFFFFFFFF00000000030000
     00044E6F6465210000000000000000000000FFFFFFFFFFFFFFFF000000000000
     0000085465726D696E616C210000000000000000000000FFFFFFFFFFFFFFFF00
     00000000000000085465726D696E616C210000000000000000000000FFFFFFFF
     FFFFFFFF0000000000000000085465726D696E616C2100000000000000000000
     00FFFFFFFFFFFFFFFF0000000000000000085465726D696E616C1D0000000000
     000000000000FFFFFFFFFFFFFFFF0000000003000000044E6F64652100000000
     00000000000000FFFFFFFFFFFFFFFF0000000000000000085465726D696E616C
     210000000000000000000000FFFFFFFFFFFFFFFF000000000000000008546572
     6D696E616C210000000000000000000000FFFFFFFFFFFFFFFF00000000000000
     00085465726D696E616C210000000000000000000000FFFFFFFFFFFFFFFF0000
     000000000000085465726D696E616C1D0000000000000000000000FFFFFFFFFF
     FFFFFF0000000003000000044E6F6465210000000000000000000000FFFFFFFF
     FFFFFFFF0000000000000000085465726D696E616C2100000000000000000000
     00FFFFFFFFFFFFFFFF0000000000000000085465726D696E616C210000000000
     000000000000FFFFFFFFFFFFFFFF0000000000000000085465726D696E616C21
     0000000000000000000000FFFFFFFFFFFFFFFF0000000000000000085465726D
     696E616C}
 end
 object btnExecute: TButton
   Left = 6
   Top = 406
   Width = 75
   Height = 25
   Caption = "Execute"
   TabOrder = 1
   OnClick = btnExecuteClick
 end
 object btnAbort: TButton
   Left = 86
   Top = 406
   Width = 75
   Height = 25
   Caption = "Abort"
   TabOrder = 2
   OnClick = btnAbortClick
 end
end


Это на скорую руку.

> Сначала уточни, может ли измениться содержимое списка узлов
> в период между паузой и возобновлением ..


Тут дело обстоит так:

если элемент уже был посещен, то он изменятся не может (т.е. его детишки неприкосновенны). С непосещенными узлами может делаться все что угодно. Небольшая доработка кода позволит контролировать это.


 
Сергей М. ©   (2006-05-29 11:47) [11]


> изменятся не может (т.е. его детишки неприкосновенны)


Смена индекса узла в списке узлов (например, при сортировке) - это тоже изменение списка.

Добавление нового узла в список узлов в промежуток между паузой и возобновлением - это тоже изменение списка.

Обе эти ситуации приведут к неработоспособности твоего алгоритма, потому что твой доп.поток не знает об этих возможных изменениях.


 
Schooler   (2006-05-29 12:51) [12]

To Сергей М. ©

1. Сказано же "на скорую руку".
2.
> Смена индекса узла в списке узлов (например, при сортировке)
> - это тоже изменение списка.
В моей задаче это исключено.

3.
> Добавление нового узла в список узлов в промежуток между
> паузой и возобновлением

Уточняю: "С непосещенными узлами может делаться все что угодно. Небольшая доработка кода позволит контролировать это." Т.е. узлы у которых AbsoluteIndex>Current

procedure TContinueThread.Execute;
Var
i:integer;
begin
for i:=0 to Count-1 Do begin
  Current := i;
  Synchronize(WaitForContinue);
end;
Terminate;
end;


Неужели сложно заменить цикл  for на While  и делать, например, после добавления/удаления узла в дерево ContinueThread.Count := TreeView1.Items.Count ?


 
Сергей М. ©   (2006-05-29 13:03) [13]

А зачем вообще тут доп.тред понадобился ?
Судя по коду (пусть даже и на скорую руку) не вижу в нем никакой необходимости.
К тому же suspend в осн.треде - это большая засада.


 
Schooler   (2006-05-29 13:38) [14]

To Сергей М. ©   (29.05.06 13:03) [13]


> А зачем вообще тут доп.тред понадобился ?

См. Schooler   (22.05.06 16:42) [3]

Давай свой вариант без доп.треда.


> К тому же suspend в осн.треде - это большая засада.


Что Вы называете осн.тредом?


procedure TContinueThread.WaitForContinue;
Var
 MyLocalVar0,..,MyLocalVarN :AnyType;
begin
if Form1.TreeView1.Items[Current].HasChildren
then
  begin

    // Некоторые действия над
    //  MyLocalVar0,..,MyLocalVarN
    // Т.е. то, что мне и требовалось: я не хочу покидать тело процедуры !!!
    // Конец   Некоторые действия

    Form1.TreeView1.Selected := Form1.TreeView1.Items[Current];
    Form1.ActiveControl:=Form1.btnExecute;
    Self.Suspend;   end
else Self.Resume;
end;


Где здесь засада?


 
Сергей М. ©   (2006-05-29 14:01) [15]


> Где здесь засада?


> Self.Suspend;   end <- здесь



> Что Вы называете осн.тредом?


Основной кодовый поток процесса.


 
Сергей М. ©   (2006-05-29 14:12) [16]


> Давай свой вариант без доп.треда.


var
 SuspendFlag: Boolean;
 NodeFrom: Integer;
..
 
procedure TreeWalking(TV: TTreeView; var NodeFrom: Integer);
begin
 with TTreeView do
 while not SuspendFlag and (NodeFrom < Items.Count) do begin
  ...
  Application.ProcessMessages;
  Inc(NodeFrom);
 end;
end;

...

procedure TMyForm.ButtonStartWalkingClick;
begin
  NodeFrom := 0;
  SuspendFlag := False;
  TreeWalking(MyTreeView, NodeFrom);
end;

procedure TMyForm.ButtonSuspendStopWalkingClick;
begin
  SuspendFlag := True;
end;

procedure TMyForm.ButtonResumeWalkingClick;
begin
  SuspendFlag := False;
  TreeWalking(MyTreeView, NodeFrom);
end;


 
Schooler   (2006-05-29 15:14) [17]

Я так понимаю, здесь еще:

procedure TMyForm.FormCreate(Sender: TObject);
begin
 Application.OnMessage := AppMessage;
end;


и


procedure TMyForm.AppMessage(var Msg: TMsg; var Handled: Boolean);
begin
 SuspendFlag := not SuspendFlag;
end;

???


 
Сергей М. ©   (2006-05-29 15:21) [18]


> Schooler   (29.05.06 15:14) [17]


Это зачем ?
Поясни ход своих мыслей с учетом [16], если таковые имеются ..


 
Schooler   (2006-05-29 15:46) [19]


> Это зачем ?


Мне надо после каждого итема остановится, попялиться на экран, осмыслить пережитое (ну типа трассировка, что-ли), и продолжить дальше движение (ButtonResumeWalkingClick) тогда , когда я захочу. Если угодно, похоже на пошаговую отладку.
С учетом [17] Твой вариант замечательно работает, только я же говорил, что я не хочу покидать тело процедуры при остановке(паузе). В Твоем варианте (когда я жму ButtonResumeWalking) я каждый раз покидаю/вхожу тело procedure TreeWalking!!!


 
Сергей М. ©   (2006-05-29 16:21) [20]


> В Твоем варианте (когда я жму ButtonResumeWalking) я каждый
> раз покидаю/вхожу тело procedure TreeWalking


И что в том страшного ?


 
Schooler   (2006-05-29 16:23) [21]

Да блин для меня страшно! Там выше смотри.
Ладно, спасибо ! Извини, ухожу.


 
Сергей М. ©   (2006-05-29 16:57) [22]

Я та ки не понял, к чему ты упомянул доп.треды .

Всуе ?



Страницы: 1 вся ветка

Текущий архив: 2006.07.09;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.029 c
2-1151031762
nickhilo
2006-06-23 07:02
2006.07.09
Компонент RichEdit с полноценной поддержкой формата RTF.


15-1150107969
Иксик
2006-06-12 14:26
2006.07.09
День России


1-1148965617
tany
2006-05-30 09:06
2006.07.09
импорт данных из Excel


2-1150568892
PRT
2006-06-17 22:28
2006.07.09
Как найти handlu всех открытых приложений ???


1-1148564081
Volf_555
2006-05-25 17:34
2006.07.09
Восстановление TRAY-значка