delphi OnCloseQuery能否防止数据丢失

zysjyyx4  于 2022-11-23  发布在  其他
关注(0)|答案(2)|浏览(152)

H1我已经写了一个小的过程来使用OnCloseQueryApplication.Terminate之前保存数据。我想知道在电源故障或计算机崩溃的情况下这是否足够。

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;

先谢谢你了。

编辑

我按照大卫Heffernan的建议修改了代码。

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;
vxqlmq5t

vxqlmq5t1#

这在电源故障或计算机崩溃的情况下是足够的
不,一点也不。
回答完这个问题后,让我们看看OnCloseQuery到底是在哪里触发的,这样您就可以知道您还可能遗漏了什么:

  • (至少在 Delphi 5中)当 Windows 会话即将结束并且要求每个正在运行的进程正常关闭时,会调用该函数:
procedure TCustomForm.WMQueryEndSession(var Message: TWMQueryEndSession);
begin
  Message.Result := Integer(CloseQuery and CallTerminateProcs);
end;

当使用者选择结束阶段作业,或当应用程序呼叫其中一个系统关机函式时,就会传送WM_QUERYENDSESSION消息。如果有任何应用程序传回零,阶段作业就不会结束。

请记住,像TerminateProcess()这样简单的操作会杀死正在运行的程序,而不会让它有任何机会继续执行指令。此外,在主程序的线程上使用SuspendThread()也会使它无限地挂起,因此您的代码也不会执行。

cxfofazt

cxfofazt2#

有人评论说,如果断电或计算机崩溃,没有什么可以帮助。这并不完全正确。但在这种情况下,唯一可以帮助的是:

  • 一个UPS (Uninterruptible Power Supply),正如大卫Heffernan提到的(这只会在电源故障的情况下有帮助)。
  • 定期保存数据,而不是等待窗体或应用程序关闭。

在后一种情况下,存在两个潜在问题:

  • 您仍将丢失自上次定期保存以来的所有未保存数据(如果您经常保存,则会最大限度地减少)。
  • 定期保存 * 期间 * 发生电源故障或计算机崩溃。根据您的要求,这可能是一个可接受的风险,但避免此问题的方法是每次保存在不同的位置,可能在最近一次定期保存成功完成后删除以前的定期保存。

数据库通常支持事务(通常称为COMMITROLLBACK,请参见ACID),因此在保存数据期间发生断电时,数据“只是”丢失,而不会覆盖或使以前的保存无效。

相关问题