Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.07.09;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.52 MB
Время: 0.01 c
2-1150881191
Dmitrij_K
2006-06-21 13:13
2006.07.09
Номер выделенной строки в StringGrid


2-1150212253
Mr tray
2006-06-13 19:24
2006.07.09
#13#10


2-1150534664
Borisss
2006-06-17 12:57
2006.07.09
Как высчитать arccos(x)?


6-1141205541
Владимир__
2006-03-01 12:32
2006.07.09
WebBrowser и картинки


1-1147442827
Igor Stepanov
2006-05-12 18:07
2006.07.09
Написание Button.Caption в две строки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский