procedure TForm2.Button1Click(Sender: TObject);
var
Strs:TStringList;
strs2:TStringList;
i,n:Integer;
codeage,sexno: integer ;
Sql:string;
begin
codeage:=1960;
sexno:=1;
Strs:=TStringList.Create;
strs2:=TStringList.Create;
Strs.LoadFromFile(AdvFileNameEdit1.Text);
SetLength(ErrStr,Strs.Count);
AdvColumnGrid1.RowCount:=Strs.Count;
DB.BeginTransaction;
for I := 0 to Strs.Count - 1 do
  begin
     Application.ProcessMessages;
     strs2.Delimiter:='|';
     strs2.DelimitedText:=Strs[i];
     if (Strs2.Count<6) or( Strs2.Count>6)then
        begin
          ErrStr[i]:='第'+inttostr(i+1)+'条记录导入格式错误!';
          continue;
        end;
     if DataModule4.IsChar(strs2[0])=False then
        begin
          ErrStr[i]:='第'+inttostr(i+1)+'条记录第一部分文本错误!' ;
          continue;
        end;
     if DataModule4.IsChar(strs2[1])=False then
        begin
          ErrStr[i]:='第'+inttostr(i+1)+'条记录第二部分文本错误!' ;
          continue;
        end;
     if DataModule4.IsChar(strs2[2])=False then
        begin
          ErrStr[i]:='第'+inttostr(i+1)+'条记录第三部分文本错误!' ;
          continue;
        end;
     if DataModule4.Ident(strs2[3],codeage,sexno)<>''then
        begin
          ErrStr[i]:='第'+inttostr(i+1)+'条记录身份证号码错误!';
          continue;
        end;
     AdvColumnGrid1.Cells[1,i+1]:=strs2[0];
     AdvColumnGrid1.Cells[2,i+1]:=strs2[1];
     AdvColumnGrid1.Cells[3,i+1]:=strs2[2];
     AdvColumnGrid1.Cells[4,i+1]:=strs2[3];
     AdvColumnGrid1.Cells[5,i+1]:=strs2[4];
     AdvColumnGrid1.Cells[6,i+1]:=strs2[5];
     try
     Sql:='select '+QuotedStr(strs2[0])+' from town where town='+QuotedStr(strs2[0]);
     if DB.GetTable(Sql).EOF then
      begin
       Sql:='insert into town(T_id,town)values((select max(T_id) from town)+1,'+QuotedStr(strs2[0])+')' ;
       DB.ExecSQL(sql);
      end;
      Sql:='select * from Village where VillageN='+QuotedStr(strs2[1]);
     if DB.GetTable(Sql).EOF then
      begin
       Sql:='insert into Village(V_id,T_id,VillageN)values((select max(V_id) from Village)+1 ,(select T_id from town where town='+QuotedStr(strs2[0])+'),'+QuotedStr(strs2[1])+')' ;
       DB.ExecSQL(sql);
      end;
     Sql:='select * from people where idno='+QuotedStr(strs2[3]);
     if DB.GetTable(sql).EOF then
      begin
        sql:='insert into people(T_id,V_id,name,idno,plans,Copies)values((select T_id from town where town='+QuotedStr(strs2[0])+'),(select V_id from Village where Villagen='+QuotedStr(strs2[1])+'),'+QuotedStr(strs2[2])+','+QuotedStr(strs2[3])+','+QuotedStr(strs2[4])+','+QuotedStr(strs2[5])+')';
        DB.ExecSQL(sql);
      end else
      begin
        sql:='update people set times=(select times from people where idno='+QuotedStr(strs2[3])+')+1 where idno='+QuotedStr(strs2[3]) ;
        DB.ExecSQL(sql);
      end;
     except
      ShowMessage('导入失败');
     end;
Application.ProcessMessages;
   end;
    for n:=Low (ErrStr) to High(ErrStr) do
        begin
          if errstr[n]<>''then
          ShowMessage(errstr[n]);
        end;
     Strs.Free;
     strs2.Free;
     SetLength(ErrStr,0);
end;procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if DB.IsTransactionOpen then
  begin
      case Application.MessageBox('是否保存导入数据', '提示', MB_OKCANCEL + MB_ICONQUESTION
        + MB_TOPMOST) of
           IDOK:
           begin
            DB.Commit;
            end;
           IDCANCEL:
           begin
            DB.Rollback;
            end;
      end;
  end;
  if DB.IsTransactionOpen=False then
    begin
    DB.Free;
    Action := caFree;
    form2 := nil;
  end;
上面的代码,要有Application.ProcessMessages,同时导入数据太多时1000条,就会提示错误,数据少的时候正常,
如果把Application.ProcessMessages删除,则多少数据导入都正常,但是界面要假死
请老师们指点一下,我用的是SQLITE数据库,连接数据库用的是SQLiteTable3

解决方案 »

  1.   

    Application.ProcessMessages;在一个For循环里你使用了两次Application.ProcessMessages,删除一开始那个试试
      

  2.   

    确实没什么必要连续用两次Application.ProcessMessages,其实这两个Application.ProcessMessages是连续运行的。不过你说的错误我觉得和这个无关,很可能是运行得太久,楼主在多次按了Button1,结果在执行Application.ProcessMessages时候出现Button1Click这个过程重入。
      

  3.   

    ,感谢帮助,晚上的时候我仔细的检查了一下,确定只有一个Application.ProcessMessages的情况下。每次导入的记录只要超过2500条。系统就报错。
    多一条都不行,检查了很久,也没看出那里有错误
      

  4.   

    还有个问题,就是SQLITE对很多其他数据库的特性都不支持,所以我只好把一些数据的检查,放在了程序里面,看起来很冗繁,请老师们帮忙看下,给点思路,看能不能简化一下,谢谢,小弟初学,见笑了。
      

  5.   

    二楼分析的有道理,可能是过程重入
    虽然LZ没贴错误信息,但感觉是在过程执行过程中多点了几次按钮导致的.
    最好在过程开始时Disable了按钮,结束后Enable.
    否则被重入后会破坏过程的数据(堆与栈)
      

  6.   

    要想界面不出现假死,就把过程放在线程中,在OnTerminate是通知一下主窗体即可
      

  7.   

    增加一个变量Flag调用前flag:=False  ;即可防止重入;procedure TForm2.Button1Click(Sender: TObject);
    var
      if Flag then Exit;
      try
        你自己的代码
      finally
        Flag:=False;
      end;
    end;
    但我觉得你事物开启了,提交了吗,如果每次2500条出现错误,我觉得应该事物太大的原因,可以把一个大事物拆成若干个小事物一般就可以了。
      

  8.   

    跟蹤斷點呢
    1.定義一個boolean變量,初始為false,然後用try...finally..end容錯包起來
    2.最好寫一個線程過程,然後調用
      

  9.   


    错误提示首先谢谢各位的解答
    1.把Button1.Enabled:=False之后试了一下,任然报错,我觉得不像是重入的问题,因为只要我删除了Application.ProcessMessages,则一切都正常。
    2.事物过大,我试过开事物SQLITE可以一次插入10万,也没出现这样的问题。
    3.自己觉得应该是Application.ProcessMessages与SQLITE事物之间有什么冲突一样。
    我提交事物是在点击Application.MessageBox的对话框处,请老老师们帮忙看看。
      

  10.   

    这个错误信息没多大帮助,不过既然在Application.ProcessMessages期间发生错误那就应该在处理数据期间发生了新的事件结果在调用Application.ProcessMessages时候处理这些事件出错的,你可以在出错时候选择Break然后查看一下当前的调用堆栈。
      

  11.   

    改变一下在OnCloseQuery中处理,同时先将关闭动作忽略,再用时钟启动保存过程,结束后再调用窗体关闭,
    窗体关闭过程不需要
    我只是猜测,可能在OnClose中调用Application.ProcessMessages后部分资源通过消息释放掉了
    可以试试用一个按钮来触发保存过程,而不是在OnClose中触发另外
    “  if DB.IsTransactionOpen=False then
        begin
        DB.Free;
        Action := caFree;
        form2 := nil;
      end;

    以上在OnDestroy做:
    “if DB.IsTransactionOpen=False then
        begin
        DB.Free;
        end;
    ”“Action := caFree;
      form2 := nil;”
    可以去掉,没必要加,这时候form2并没有释放,其他地方要是有使用会报错。。以上只是建议,也许是
     “    if DB.GetTable(Sql).EOF then
          begin
           Sql:='insert into town(T_id,town)values((select max(T_id) from town)+1,'+QuotedStr(strs2[0])+')' ;
           DB.ExecSQL(sql);
          end;
    ”过程存在一些未执行消息处理,调用Application.ProcessMessages;后会处理这些未执行消息处理而报错,