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

Вниз

Выполнение по шагам   Найти похожие ветки 

 
hellmachine   (2003-12-23 00:58) [0]

Добрый вечер, мастера!
У меня есть задача представить выполнение некоторых вычислений по шагам, на подобие отладки, где вычисления выполняются в цикле до опр. момента, затем останавливаются, пользователь смотрит результат, нажимает "след. шаг" и вычисления продолжаюстся. Я попытаюсь привести здесь свое решение, а к вам просьба оценить его на на безопасность или элегантность :)
Заранее хочу оговориться, что опыта у меня в написании многопоточных приложений - ноль и возможно мой вариант, мягко говоря, не самый удачный или безопасный.
Такую задачу можно было бы решить и реализовав что-то наподобие стандартного мастера windows, но разбивать вычисления и помещать их в несколько обработчиков нажатся на кнопку "далее" мне показалось нездорово и я решил связаться с потоками.
Вот общая схема:
* вычисления выполняются в методе Execute потока
* в потоке объявляются события (TNotifyEvent) и при выполнении опр. условия они вызываюстя след. образом прямо из тела TMyThread.Execute без Synchronize (вроде как событие не метод):

if @FMyEvent <> nil then
begin
FMyEvemt(Self);
Suspend();
end;

* в обработчике этого события выводим данные на экран
* по нажатии на кнопку "след. шаг" - MyThread.Resume();

вроде все работает, но я меня терзают смутные сомнения - нельзя ли сделать проще/надежней


 
Юрий Зотов ©   (2003-12-23 02:13) [1]

> hellmachine (23.12.03 00:58)
> вроде как событие не метод

А обработчик события? Разве это не метод? Вот этот код: FMyEvent(Self) - разве это не есть вызов метода?

Он самый и есть. Да еще связанный с обновлением каких-то визуальных контролов - значит, этот метод как раз потоконебезопасный и его надо вызывать через Synchronize.

IMHO, здесь вполне уместно использовать примерно такую схему:

procedure TMyThread.CallMyEvent;
begin
// FMyEventAssigned - это булевское поле в классе потока
FMyEventAssigned := Assigned(FMyEvent);
if FMyEventAssigned then FMyEvent(Self)
end;

procedure TMyThread.Execute;
var
i: integer;
begin
i := 0;
// Проверка Terminated позволяет легко ввести кнопку "Стоп"
while not Terminated and (i <= Последний_шаг) do
begin
case i of:
0: ... // первая порция вычислений
1: ... // вторая порция вычислений
...
Последний_шаг: // последняя порция вычислений
end;
Synchronize(CallMyEvent); // Безопасное обновление экрана.
if FMyEventAssigned then Suspend;
Inc(i);
end
end;

А в обработчике кнопки "Следующий шаг" просто вызываем Resume.


 
hellmachine   (2003-12-24 15:15) [2]

спасибо - написал, работает;


 
hellmachine   (2003-12-24 23:17) [3]

при тестировании выяснилась одна интересная вешь: вычисления в самодельном потоке выполняются значительно медленее, чем в основном - даже при условии, что основной поток простаивает; причем установка приоритета потока слабо влияет на результат. как это побороть?

также была замечена очень интересная особенность: значительного ускорения выполнения можно достичь, тыкая мышкой на элементы управления (например, выделяя item"ы в TListView) - прирост производительности до 100%!!! как это понимать?!!



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

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

Наверх




Память: 0.48 MB
Время: 0.016 c
4-25654
Testerman
2003-11-05 19:03
2004.01.09
Помогите заменить кнопку


3-25216
DJohn
2003-12-05 14:27
2004.01.09
Dbexpress. Стоит ли?


9-25173
Mihey
2003-06-21 00:24
2004.01.09
Non full screen DirectX...


14-25498
w3ser
2003-12-18 22:25
2004.01.09
Очередные нападки Microsoft на пользователей Opera и Mozilla


6-25489
BJValentine
2003-11-06 11:12
2004.01.09
Сокеты