Home > Software design >  Can OnCloseQuery protect data loss
Can OnCloseQuery protect data loss

Time:11-19

H1 I have written a little process to save data before Application.Terminate using OnCloseQuery. I was wondering whether this is sufficient in the event of a power failure or a computer crash.

type
    TForm1 = class(TForm)
        abs: TABSDatabase;
        ABSTable1: TABSTable;
        .... 
        ABSTable6: TABSTable;
    ....    
var
Form1: TForm1;
isBusy : Boolean;
....
procedure TForm1.CloseTables;
 var
    x : Integer;
    dummy : TABSTable;
begin
     for x:=0 to ComponentCount-1 do
     begin
         if Components[x] is TABSDataSet then
             begin
                 if Components[x] is TABSTable  then
                 begin
                     dummy := (Components[x] as TABSTable);
                     if ((dummy.Active = True) and ((dummy.state = dsEdit) or (dummy.State = dsInsert))) then
                         begin
                             dummy.Post;
                             dummy.Active := False;
                         end
                       else
                         if dummy. Active = True then dummy.Close;                               
                 end;
             end;
     end;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
        if abs.Connected = True then isBusy := True else isBusy := False;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
    if isBusy = True then
        begin
            CanClose := False;
            CloseTables;
            abs.Connected := False;
            isBusy := False;
            Application.Terminate;
        end
        else CanClose := True;
end;

Thank you in advance.

Edit

I modified my code following David Heffernan's advice.

procedure TForm1.CloseTables;
 var
  x : Integer;
  dummy : TABSTable;
begin
   for x:=0 to ComponentCount-1 do
   begin
     if Components[x] is TABSDataSet then
       begin
         if Components[x] is TABSTable  then
          begin
            dummy := (Components[x] as TABSTable);
            if ((dummy.Active) and ((dummy.state = dsEdit) or (dummy.State = dsInsert))) then
              begin
                dummy.Post;
                dummy.Active := False;
              end
            else
              if dummy.Active then dummy.Close;
          end;
       end;
   end;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if abs.Connected then
    begin
      CanClose := False;
      CloseTables;
      abs.Connected := False;
      Application.Terminate;
    end
  else CanClose := True;
end;

CodePudding user response:

this is sufficient in the event of a power failure or a computer crash

No, not at all.

After answering that question let's take a look where OnCloseQuery is triggered at all, so you can sense what else you might miss:

  • (At least in Delphi 5) It is invoked when the Windows session was about to end and every running process was asked to close gracefully:
    procedure TCustomForm.WMQueryEndSession(var Message: TWMQueryEndSession);
    begin
      Message.Result := Integer(CloseQuery and CallTerminateProcs);
    end;
    

    The WM_QUERYENDSESSION message is sent when the user chooses to end the session or when an application calls one of the system shutdown functions. If any application returns zero, the session is not ended.

  • When .Close() is called - the typical call to close one of your windows (forms).
  • When internally .CloseModal() is called.

Keep in mind that something as easy as TerminateProcess() will kill your running program without letting it any chance of still executing instructions. Furthermore using SuspendThread() on your main program's thread can also hang it right there infinitly, so your code isn't executed either.

CodePudding user response:

A comment was made that nothing can help if you lose power or the computer crashes. That is not completely correct. But the only things that can help in such cases are:

  • A UPS (Uninterruptible Power Supply), as David Heffernan mentioned (which will only help in the case of a power failure).
  • Saving data periodically instead of waiting for the form or application to close.

In the latter case, there are two potential problems:

  • You will still lose any unsaved data since the last periodical save (which will be minimised if you save frequently).
  • The power fails or the computer crashes during a periodical save. Depending on your requirement this might be an acceptable risk, but the way to avoid this problem is to save in a different place each time, perhaps deleting the previous periodical save after the latest periodical save has successfully completed.

As I have not used databases, I cannot say how that should be done with databases.

  • Related