Self-debugger

  • Автор темы a3design
  • Дата начала
Статус
Закрыто для дальнейших ответов.
A

a3design

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

Процедура Print у меня просто рисует графики и диаграмы на форме, с этим проблем нет, но при таком способе вывода возникает проблема с задержкой, т.е. процедурой Delay. Без нее юзер ничего не увидит (итерации достаточно быстрые), а реализовывть ее за счет пустых циклов не серьезно. Обязательные требования к программе: вывод в риал-тайме и возможность регулировать (или отключить совсем :)) паузу.

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

morpheus

а через поток зделать... вот и пауза )))
 
A

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) Через некоторое время выскакивает ошибка: "Отказано в доступе". Если я правильно понял, это от того, что поток уже доработал, а таймер еще пытается им управлять.

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

morpheus

Ну тада савсем деревянный метод

в цикле зделать
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;


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


З,Ы,
 
A

a3design

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

Kmet

Well-known member
25.05.2006
904
8
BIT
0
Как сделать так, чтобы в этот момент приложение просто прикратило свою работу на время паузы (а потом естественно продолжило )?Причем независимо от того, где выполняется этот код в соновном потоке или в дополнительном. Другими словами мне нужно "воскресить" процедурку delay из Турбо Паскаля. Главные требование к процедуре

Осиановить все потоки приложения в общем случае AFAIK нельзя. Для этого надо писпть что типо менеджера потоков и т.д. и т.п.

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

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

morpheus

Возможно поможет это

 
A

a3design

2Kmet:
2. дополниетльный поток и slepp()
Это то, что было мне нужно. Спасибо, Kmet!
Можешь подробней рассказать о
3. дополнительный поток который в начале(конце) итерации приостнавливается на auto-reset event'е. А уже евент сбрасывть например из таймера.

2Morpheus:
Интересный линк, прочел где-то до половины, но там не совсем то, что мне надо (задача в статье поставлена сложнее, чем требуется). Все равно спасибо, со временем пригодится :)
 
Статус
Закрыто для дальнейших ответов.
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!