Форум: "Основная";
Текущий архив: 2004.01.09;
Скачать: [xml.tar.bz2];
ВнизВыполнение по шагам Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.45 MB
Время: 0.014 c