Как прекратить выполнение события из продцедуры?

InterSky
Дата: 09.09.2019 13:56:23
Произошло какое-то событие, ну допустим OnButton.Click, и оно выполняется...
Если в теле этого события встретится Exit, то выполнение прекращается.
Но если, в нём вызывается процедура, и уже в ней встретится Exit, то прекратится исполнение только этой процедуры. А можно ли из процедуры остановить выполнение всего события?

Конечно можно делать костыли: можно превратить процедуру в функцию, и в ней перед выходом подавать значение: выполнилась нормально или прекратила работу через Exit, а потом на основания полученного от функции значения делать такой же выход и в блоке вызвавшем функцию. Но это костыли! Возможно тут кто-то возмущённо скажет, что НЕТ, что Именно так и должна работать программа, последовательно и продуманно выполняя каждое действие... Но по такой логике и Exit не должен существовать, а тем более ужасный Halt.

Ну или как аналог взять циклы: там есть Continue (так же как Exit прерывающий выполнение блока), но есть и Break - который прекращает выполнение всего цикла (вот аналог такого для прекращения события я и ищу).

P.S. Предвижу что кто-то вместо решения задачи, будет говорить о лени, о том что дескать поставить одну проверку, или даже вписать вместо простого вызова процедуры, конструкцию типа: if MyFunction=666 then Exit - это даже красиво... Но эти процедура приводящая к остановке может иметь и десятую степень вложенности, и тогда переделывать процедуры в функции надо будет в десятках мест. Да и где-то может оказаться что остановка произойдёт в функции, а она уже и так что-то возвращает...
Тут сразу же появятся люди которые предложат проверять не возвращаемое событие, а специально созданную глобальную переменную. И по всему коду, на всех уровнях вложенности, после выхода из каждой процедуры или функции связанной с этим событием надо будет выставлять проверки выхода (если внутри могла быть изменена эта глобальная переменная).

Тут уже кто-то ужаснётся - Что так у тебя за монстр, многоуровневый и остановить которого может потребоваться не в одном каком-то месте, а во многих местах на разных уровнях?
Всё просто: Одна кнопка, и она вызывает событие который производит анализ большого массива данных. Расчёты производятся десятками разных методов. У каждого разный метод. Где-то идём рекурсивно, где-то проверяем на возможность ошибок перебором углубляясь вглубь и сравнивая с другими блоками массива, где-то пытаемся вычислить что может произойти и просчитываем дальнейшие решения на базе имеющихся данных, чтобы предугадать события, где-то просто оптимизируем меняя одну последовательно данных на другую... И на разных уровнях вложенности есть возможность отображения на экране (изменение данных, изменение данных, отметка области с ошибками, удаление того что не повлияет ни на что... Всем выводом занимается одна процедура (вызываемая из сотни мест на разных уровнях вложенности процедур и функций). И чтобы сделать пошаговый вывод, достаточно было бы в конце этой функции вызвать какой-то условный GlobalExit (или EventExit), который бы остановил всё действие единственного события. Чтобы оператор проанализировал изменения, и принял решение о продолжении анализа уже с другими параметрами или с другим приоритетом или в другом направлении. Не хочется в случае пошагового режима после каждого вывода данных делать бесконечный цикл (таким образом останавливая работу программы) и Halt'ить её для того чтобы оператор продолжил анализ с другими параметрами.
Aniskin
Дата: 09.09.2019 14:11:07
type
  EEverythingIsOk = class(Exception);

procedure Job;
begin
  // Some code
  if SomeCondition then 
    raise EEverythingIsOk.Create(''); // вместо Exit
  // Some code
end;

procedure TForm6.btn1Click(Sender: TObject);
begin
  try
    Job;
  except
    on E: EEverythingIsOk do
    else raise;
  end;
end;
Dimitry Sibiryakov
Дата: 09.09.2019 14:14:49

Aniskin
raise EEverythingIsOk

Обычно используется Abort;

Posted via ActualForum NNTP Server 1.5

wadman
Дата: 09.09.2019 14:48:08
InterSky
А можно ли из процедуры остановить выполнение всего события?

Можно процедуру объявить функцией и анализировать её результат.
InterSky
Дата: 09.09.2019 15:19:53
wadman
InterSky
А можно ли из процедуры остановить выполнение всего события?

Можно процедуру объявить функцией и анализировать её результат.

Процедура которую вы предложили объявить функцией и анализировать её результат, сама может быть вызвана из другой функции вызванной из процедуры сработавшей по OnClick. Этот вариант предусмотрительно разобран в вопросе, чтобы заранее избавиться от ответов типа вашего...

Aniskin - спасибо!
goldmi45
Дата: 09.09.2019 15:30:40
InterSky, обработка исключительных ситуаций может вам помочь.
InterSky
...
Ну или как аналог взять циклы: там есть Continue (так же как Exit прерывающий выполнение блока), но есть и Break - который прекращает выполнение всего цикла (вот аналог такого для прекращения события я и ищу).


Break прерывает цикл, но не прерывает процедуру. Exit - прерывает не только цикл, но и процедуру.
rgreat
Дата: 09.09.2019 15:35:10
Dimitry Sibiryakov
Обычно используется Abort;
+1
InterSky
Дата: 09.09.2019 17:07:51
goldmi45
InterSky, обработка исключительных ситуаций может вам помочь.
InterSky
...
Ну или как аналог взять циклы: там есть Continue (так же как Exit прерывающий выполнение блока), но есть и Break - который прекращает выполнение всего цикла (вот аналог такого для прекращения события я и ищу).


Break прерывает цикл, но не прерывает процедуру. Exit - прерывает не только цикл, но и процедуру.

Вы знаете что такое аналогия?
Представьте язык программирования, в котором нету циклов (а так же goto и рекурсии). Если вам надо было бы что-то выполнить в цикле от 1 до 5, вы бы писали:
procedure outerProc;

 Procedure innerProc(const n : Integer);
 begin
 // Тут пишется то что вы писали бы в теле цикла.
 end;

begin
innerProc(1);
innerProc(2);
innerProc(3);
innerProc(4);
innerProc(5);
end;


То есть, цикл - это процедура внутри процедуры.
Если вместо комментария вы впишите текст программы и там встретится Exit, он сработает как Continue в циклах и завершит лишь внутреннюю процедуру "innerProc". По аналогии, встречающийся в цикле Break завершил бы внешнюю процедуру "outerProc".
ёёёёё
Дата: 09.09.2019 17:22:38
InterSky,

"Выдыхай, бобер" - ©.
makhaon
Дата: 09.09.2019 18:10:34
InterSky,

автор
Но если, в нём вызывается процедура, и уже в ней встретится Exit, то прекратится исполнение только этой процедуры. А можно ли из процедуры остановить выполнение всего события?


надежнее и проще всего решается исключениями