Using Abort to Improve / Simplify Code in Some Situations

I had a discussion one of these days: https://stackoverflow.com/a/166648// where I did not quite understand why it Abortwas better than a challenge Exitin this situation. I try not to use it in the code stream. I find this to be bad practice and bad for code flow. but the @David expression in the comments made me think, maybe I missed something:

Without a silent exception, how would you interrupt an operation when down a call stack. For example, how would you stop copying a file using 10 deep call stacks? Isn't that exactly what exceptions are for? Of course, you can encode it without exception, but it is much more verbose and error prone.

I can not imagine such a situation. Can someone give me an example of such code / script and convince me that Abortin the above case is really a good thing and "much more verbose and error prone". (3-4 call stacks are enough to illustrate)

+4
source share
2 answers

The simplest scenario that illustrates my point is:

procedure MethodA;
begin
  MethodB;
  MethodC;
end;    

procedure MethodB;
begin
  // ... do stuff
end;

procedure MethodC;
begin
  // ... do stuff
end;

It's fine. Now suppose that MethodBthe user asks for some input, and if the user clicks the Cancel button , then further work should not be performed. You can implement this as follows:

procedure MethodA;
begin
  if MethodB then
    MethodC;
end;    

function MethodB: Boolean;
begin
  Result := MessageDlg(...)=mrOK;
  if not Result then
    exit;
  // ... do stuff
end;

procedure MethodC;
begin
  // ... do stuff
end;

, , , . , MethodB, , . .

, , MethodB . :

procedure MethodA;
begin
  MethodC(MethodB);
end;    

function MethodB: string;
begin
  Result := ...;
end;

procedure MethodC(Value: string);
begin
  // ... do stuff with Value
end;

, , . MethodB? out ? , , . , , , .

procedure MethodA;
var
  Value: string;
begin
  if MethodB(Value) then
    MethodC(Value);
end;    

function MethodB(out Value: string): Boolean;
begin
  Result := MessageDlg(...)=mrOK;
  if not Result then
    exit;
  Value := ...;
end;

procedure MethodC(Value: string);
begin
  // ... do stuff with Value
end;

, , , . , EAbort, Abort, , . - , .

:

procedure MethodA;
begin
  MethodC(MethodB);
end;    

function MethodB: string;
begin
  if MessageDlg(...)<>mrOK then
    Abort;
  Result := ...;
end;

procedure MethodC(Value: string);
begin
  // ... do stuff with Value
end;

, MethodA . , MethodA MethodB .

, MethodB . string. , , , .

, , Abort. , , MethodB 4 5 ?


, Abort exit. , . Abort , , , . , , . , , .

+7

, , ( ), Application.ProcessMessages. , ( : , ..). , - . , Abort EAbort. , try/except/finally , .

// in the main thread:
procedure TMyProgressDialog.b_AbortClick(Sender: TObject);
begin
  if AskUserIfHeIsSure then begin
    gblAbortedFlag := true;
    b_Abort.Enabled := false;
    b_Abort.Caption := _('Aborting');
  end;
end;

// call this repeatedly during the lenghty operation:
procecdure CheckAborted;
begin
  // If you are in the main thread, you might want to call
  // Application.ProcessMessages;
  // here. If not, definitely don't.
  if gblAbortedFlag then
    Abort;
end;

, , - ifs .

+4

Source: https://habr.com/ru/post/1669782/


All Articles