Self-debugger

Тема в разделе "Delphi - Система", создана пользователем a3design, 2 ноя 2006.

Статус темы:
Закрыта.
  1. a3design

    a3design Гость

    Вобщем задача такая: необходимо во время работы программы выводить на форму значение переменных. Т.е. в программе есть процедура, в которой происходят итерации какого-либо алгоритма. В самом вложенном цикле должен происходить вывод этих самых переменных на экран. Выглядит это применно так:
    Код (Text):
    procedure Work;
    var
    <var1, var2, ..... varN>
    begin
    while(...)
    begin
    //тут основная работа
    Print; //Вывод
    Delay; //Задержка
    end;
    end;
    Процедура Print у меня просто рисует графики и диаграмы на форме, с этим проблем нет, но при таком способе вывода возникает проблема с задержкой, т.е. процедурой Delay. Без нее юзер ничего не увидит (итерации достаточно быстрые), а реализовывть ее за счет пустых циклов не серьезно. Обязательные требования к программе: вывод в риал-тайме и возможность регулировать (или отключить совсем :)) паузу.

    Подскажите пожалуйста как решить такую вот задачу.
     
  2. morpheus

    morpheus скриптописец

    Регистрация:
    7 авг 2006
    Сообщения:
    3.927
    Симпатии:
    0
    а через поток зделать... вот и пауза )))
     
  3. a3design

    a3design Гость

    Исчерпывающий конечно ответ ;). Ну, а если я совсем новичек, и про потоки ничего не слышал и знать не знаю (что в принципе недалеко от правды)?

    Если серьезно, пробовал с потоками и таймером. :) Вот мой код:
    [codebox]
    type

    TMainForm = class(TForm)
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    end;

    TWork=class(TThread)
    protected
    procedure Execute;override;
    procedure Print;
    public
    i,j:integer; //Эти переменные на вывод
    end;

    var
    MainForm: TMainForm;
    Work:TWork;

    implementation

    procedure TWork.Print();
    begin
    MainForm.Caption:=IntToStr(i)+' '+IntToStr(j); //Собственно весь нехитрый вывод
    end;

    procedure TWork.Execute();
    begin
    i:=0; j:=0;
    while(i<100)do
    begin
    inc(i);
    while (j<100)do
    begin
    inc(j);
    //здесь происходят вычисления
    Synchronize(Print);
    end;
    end;
    end;

    {$R *.dfm}

    procedure TMainForm.FormCreate(Sender: TObject);
    begin
    Work:=TWork.Create(true);
    end;

    procedure TMainForm.FormClick(Sender: TObject);
    begin
    Timer1.Enabled:=true;
    end;

    procedure TMainForm.Timer1Timer(Sender: TObject); //здесь я ставлю и снимаю поток с паузы
    begin
    if(Work.Suspended)then
    Work.Resume
    else
    Work.Suspend;
    end;
    [/codebox]
    Основные недостатки этого кода:
    1) Пауза происходит, но естественно не там где нужно, т.к. вызов Suspend приходится не конец каждого цикла, а на произвольное место. Таким образо, ничего не стоит пропустит парочку итераций, а это не допустимо.
    2) Через некоторое время выскакивает ошибка: "Отказано в доступе". Если я правильно понял, это от того, что поток уже доработал, а таймер еще пытается им управлять.

    Подскажите, как исправить эти баги. Пауза должна приходиться на каждый внутренний цикл.
     
  4. morpheus

    morpheus скриптописец

    Регистрация:
    7 авг 2006
    Сообщения:
    3.927
    Симпатии:
    0
    Ну тада савсем деревянный метод

    в цикле зделать
    var
    MustPause: boolean

    procedure PauseBtn.OnClick(..)
    begin
    MustPause := true;
    end;


    fucntion MyFunc
    begin
    for i := 0 to XXXX do begin
    ....
    Application.ProcessMessage
    ....
    if MustPause then begin
    /... обработка паузы
    end;
    end;


    код писался на скорую руку и с утра так шо без претезий :)


    З,Ы, Про Application.Pro....
     
  5. a3design

    a3design Гость

    Может я неправильно высказался в начале, но именно
    меня и интерисует. Как сделать так, чтобы в этот момент приложение просто прикратило свою работу на время паузы (а потом естественно продолжило :rolleyes:)?Причем независимо от того, где выполняется этот код в соновном потоке или в дополнительном. Другими словами мне нужно "воскресить" процедурку delay из Турбо Паскаля. Главные требование к процедуре
    1. Можно регулировать время паузы (желательно в широком диапазоне)
    2. Она не грузит процессор
    Я думаю это вполне выполнимо, хотя бы потому, что есть процедура GetMessage(...).
     
  6. Kmet

    Kmet Well-Known Member

    Регистрация:
    25 май 2006
    Сообщения:
    1.017
    Симпатии:
    1
    Осиановить все потоки приложения в общем случае AFAIK нельзя. Для этого надо писпть что типо менеджера потоков и т.д. и т.п.

    В твоем случае есть как мимнимум три решения
    1. однопоточное приложение и sleep (на время паузы приложение будет как бы подвисать)
    2. дополниетльный поток и slepp()
    3. дополнительный поток который в начале(конце) итерации приостнавливается на auto-reset event'е. А уже евент сбрасывть например из таймера.

    В двух последний решений возможно понадобиться дополнительная синхронизация разделяемых данных и я не уверен что вывод на канвас потокобезопасная операция
     
  7. morpheus

    morpheus скриптописец

    Регистрация:
    7 авг 2006
    Сообщения:
    3.927
    Симпатии:
    0
  8. a3design

    a3design Гость

    2Kmet:
    Это то, что было мне нужно. Спасибо, Kmet!
    Можешь подробней рассказать о
    2Morpheus:
    Интересный линк, прочел где-то до половины, но там не совсем то, что мне надо (задача в статье поставлена сложнее, чем требуется). Все равно спасибо, со временем пригодится :)
     
Загрузка...
Похожие Темы - Self debugger
  1. gregarah
    Ответов:
    3
    Просмотров:
    273
  2. puks
    Ответов:
    0
    Просмотров:
    2.961
  3. fedotxxl
    Ответов:
    1
    Просмотров:
    2.070
Статус темы:
Закрыта.

Поделиться этой страницей