powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как прекратить выполнение события из продцедуры?
32 сообщений из 32, показаны все 2 страниц
Как прекратить выполнение события из продцедуры?
    #39859320
InterSky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Произошло какое-то событие, ну допустим OnButton.Click, и оно выполняется...
Если в теле этого события встретится Exit, то выполнение прекращается.
Но если, в нём вызывается процедура, и уже в ней встретится Exit, то прекратится исполнение только этой процедуры. А можно ли из процедуры остановить выполнение всего события?

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

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

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

Тут уже кто-то ужаснётся - Что так у тебя за монстр, многоуровневый и остановить которого может потребоваться не в одном каком-то месте, а во многих местах на разных уровнях?
Всё просто: Одна кнопка, и она вызывает событие который производит анализ большого массива данных. Расчёты производятся десятками разных методов. У каждого разный метод. Где-то идём рекурсивно, где-то проверяем на возможность ошибок перебором углубляясь вглубь и сравнивая с другими блоками массива, где-то пытаемся вычислить что может произойти и просчитываем дальнейшие решения на базе имеющихся данных, чтобы предугадать события, где-то просто оптимизируем меняя одну последовательно данных на другую... И на разных уровнях вложенности есть возможность отображения на экране (изменение данных, изменение данных, отметка области с ошибками, удаление того что не повлияет ни на что... Всем выводом занимается одна процедура (вызываемая из сотни мест на разных уровнях вложенности процедур и функций). И чтобы сделать пошаговый вывод, достаточно было бы в конце этой функции вызвать какой-то условный GlobalExit (или EventExit), который бы остановил всё действие единственного события. Чтобы оператор проанализировал изменения, и принял решение о продолжении анализа уже с другими параметрами или с другим приоритетом или в другом направлении. Не хочется в случае пошагового режима после каждого вывода данных делать бесконечный цикл (таким образом останавливая работу программы) и Halt'ить её для того чтобы оператор продолжил анализ с другими параметрами.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859327
Aniskin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
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;
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859331
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aniskinraise EEverythingIsOk

Обычно используется Abort;
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859365
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
InterSkyА можно ли из процедуры остановить выполнение всего события?
Можно процедуру объявить функцией и анализировать её результат.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859387
InterSky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanInterSkyА можно ли из процедуры остановить выполнение всего события?
Можно процедуру объявить функцией и анализировать её результат.
Процедура которую вы предложили объявить функцией и анализировать её результат, сама может быть вызвана из другой функции вызванной из процедуры сработавшей по OnClick. Этот вариант предусмотрительно разобран в вопросе, чтобы заранее избавиться от ответов типа вашего...

Aniskin - спасибо!
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859394
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
InterSky, обработка исключительных ситуаций может вам помочь.
InterSky...
Ну или как аналог взять циклы: там есть Continue (так же как Exit прерывающий выполнение блока), но есть и Break - который прекращает выполнение всего цикла (вот аналог такого для прекращения события я и ищу).


Break прерывает цикл, но не прерывает процедуру. Exit - прерывает не только цикл, но и процедуру.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859399
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovОбычно используется Abort;
+1
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859455
InterSky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
goldmi45InterSky, обработка исключительных ситуаций может вам помочь.
InterSky...
Ну или как аналог взять циклы: там есть Continue (так же как Exit прерывающий выполнение блока), но есть и Break - который прекращает выполнение всего цикла (вот аналог такого для прекращения события я и ищу).


Break прерывает цикл, но не прерывает процедуру. Exit - прерывает не только цикл, но и процедуру.
Вы знаете что такое аналогия?
Представьте язык программирования, в котором нету циклов (а так же goto и рекурсии). Если вам надо было бы что-то выполнить в цикле от 1 до 5, вы бы писали:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
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".
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859464
ёёёёё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
InterSky,

"Выдыхай, бобер" - ©.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859493
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
InterSky,

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

надежнее и проще всего решается исключениями
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859496
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть еще более красивый вариант:


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
function MyProc: boolean;
begin
//
  if something then Exit(False);
//
end;


procedure Main;
begin
  If not MyProc then Exit;
end;
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859502
InterSky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatЕсть еще более красивый вариант:

If not MyProc then Exit;

Я же объяснил что и из функций тоже надо выходить...
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859503
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
InterSky,

Меняйте функцию.

funtion myFunc: integer;
на
funtion myFunc(out Res: integer): boolean;
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859504
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Собственно половина winAPI так работает.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859508
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
InterSkyЯ же объяснил что и из функций тоже надо выходить...

Слово "аборт" ты при чтении топика пропустил как "шибка нипанятное"?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859511
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Abort - медленно.
Если таких выходов предпологается много - это очень плохое решение.

Как-то у меня коллега сделал как-то так:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
function IsFloat(Text: string): boolean
begin
   try
      StrToFloat(Text);
      Result:=True;
   except
      Result:=False;
   end;
end;


А потом удивлялся, что это у него все тормозит нещадно на больших объемах данных.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859516
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatА потом удивлялся, что это у него все тормозит нещадно на больших объемах данных.

Тормозило у него в основном из-за передачи строки по значению скорее всего. SEH,
используемый для исключений, считается быстрейшим способом их обработки из всех.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859525
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
function IsFloat(const Text: string): boolean;
begin
   try
      StrToFloat(Text);
      Result:=True;
   except
      Result:=False;
   end;
end;

var
  i : integer;
  c : cardinal;
begin
  c:=getTickCount;
  for i:=0 to 1000 do begin
    IsFloat('2354fvbcv');
  end;
  writeln(getTickCount-c);
  c:=getTickCount;
  for i:=0 to 1000 do begin
    StrToFloatDef('2354fvbcv',0);
  end;
  writeln(getTickCount-c);



11297
0
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859535
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat11297
0

Ну, у меня разница не так велика, но таки да, второй цикл в 100 раз быстрее первого.
Очевидно, туда вмешиваются накладные расходы менеджера памяти. Жаль в Дельфи нельзя
выкинуть статический объект исключения.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859544
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

0.1 секунды на мнеджер памяти не списать.

Если бы дело было только в нем то было бы не 100 вызовов в секунду а как минимум 10000.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859545
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Упс, 0.01 сек. Опечатался.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859546
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat0.1 секунды на мнеджер памяти не списать.

Это у тебя что-то с таймером. Мне пришлось добавить два нуля в цикл чтобы получить
4087
47
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859547
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выброс исключения тормозит, да. Там, где предполагается частый отрицательный результат, лучше юзать возврат флага/кода ошибки
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859549
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovЭто у тебя что-то с таймером.
Не, реально 11 секунд.

Delphi 10.2, Release, Core i5-6500 3.2 GHz.
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859551
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Под x64 быстрей.

x86 - 11391
х64 - 4265
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859554
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatDelphi 10.2, Release, Core i5-6500 3.2 GHz.

Delphi 2006, AMD ноутбук пятилетней давности 1Ггц.

Походу, они что-то сломали в RTL.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859557
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Не. Надо было не из под среды запускать. Она даже в релизе ошибки отлавливает оказывается.

Теперь все как у тебя.
Код: pascal
1.
  for i:=0 to 1000000 do begin


4047
62
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859660
goldmi45
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
InterSkyТо есть, цикл - это процедура внутри процедуры.
Если вместо комментария вы впишите текст программы и там встретится Exit, он сработает как Continue в циклах и завершит лишь внутреннюю процедуру "innerProc". По аналогии, встречающийся в цикле Break завершил бы внешнюю процедуру "outerProc".
Чта?
Всегда считал, что цикл - это конструкция, предназначенная для многократного выполнения. В паскале это for, while, repeat-until.
То, что вы привели, это последовательное выполнение процедуры.
И если в outerProc вы напишете Break без цикла, то будет ошибка компиляции. Потому что break должен находиться внутри цикла (for, while, repeat-until).
Код 1:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
begin
  for i := 0 to 100 do
  begin
    writeln(Format('%d', [i]));
    if i = 9 then
      Exit;
  end;
  writeln('after loop');
end;


Код 2:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
begin
  for i := 0 to 100 do
  begin
    writeln(Format('%d', [i]));
    if i = 9 then
      Break;
  end;
  writeln('after loop');
end;



Как вы думаете, есть разница между кодом 1 и 2?
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39859682
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
InterSky,

есть еще способ, если по твоим условиям позволено менять тип и кол-во параметров процедуры (изврат, конечно, но если сильно надо) :)
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
  { TForm1 }

  TForm1 = class(TForm)
    procedure FormDblClick(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: char);
  private
    FOutParam: Integer;
    FInParam: Integer;
  public
    procedure Proc1();
    procedure Proc2(out OutParam: Integer);

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormDblClick(Sender: TObject);
begin
  Proc1();
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: char);
begin
  if Key = chr(ord(VK_ESCAPE)) then FInParam:= 1;
end;

procedure TForm1.Proc1();
begin
  Proc2(FOutParam);
  if FOutParam <> 1
    then Self.Caption:= 'был exit'
    else Self.Caption:= 'не было exit''а';
end;

procedure TForm1.Proc2(out OutParam: Integer);
var n: Integer = 0;
begin
  FInParam:= 0;
  OutParam:= 1;
  while n < 10 do
  begin
    Application.ProcessMessages;
    if FInParam > 0 then
    begin
      OutParam:= 0;
      Exit;
    end;
    inc(n);
    Self.Caption:= IntToStr(n) ;
    Sleep(500);
  end;
end;  
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39861714
Linux_64
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Попробуйте использовать вместо if then оператор выбора case или метку Label
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39861741
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
13.09.2019 17:18, Linux_64 пишет:
> Попробуйте использовать вместо if then оператор выбора case или метку Label

и шо?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Как прекратить выполнение события из продцедуры?
    #39861820
Фотография Док
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Linux_64или метку Label
а go to почему не упомянул? :)
...
Рейтинг: 0 / 0
32 сообщений из 32, показаны все 2 страниц
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как прекратить выполнение события из продцедуры?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]