关于Application.ProcessMessages奇怪的问题,代码贴出来请老师指点

LIIJIE1986 2011-02-13 12:36:09

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
...全文
309 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
CaiBirdy 2011-02-15
  • 打赏
  • 举报
回复
改变一下在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;后会处理这些未执行消息处理而报错,


manfeng 2011-02-15
  • 打赏
  • 举报
回复
这个错误信息没多大帮助,不过既然在Application.ProcessMessages期间发生错误那就应该在处理数据期间发生了新的事件结果在调用Application.ProcessMessages时候处理这些事件出错的,你可以在出错时候选择Break然后查看一下当前的调用堆栈。
kye_jufei 2011-02-14
  • 打赏
  • 举报
回复
跟蹤斷點呢。。。
1.定義一個boolean變量,初始為false,然後用try...finally..end容錯包起來。。。
2.最好寫一個線程過程,然後調用。。。
LIIJIE1986 2011-02-14
  • 打赏
  • 举报
回复

刚才发的图片,失败了,现在重发
LIIJIE1986 2011-02-14
  • 打赏
  • 举报
回复

错误提示[Quote=引用 8 楼 sundayzhao 的回复:]
增加一个变量Flag

调用前flag:=False ;即可防止重入;

procedure TForm2.Button1Click(Sender: TObject);
var
if Flag then Exit;
try
你自己的代码
finally
Flag:=False;
end;
end;


但我觉得你事物开启了,提交了吗,如果每次2……
[/Quote]
首先谢谢各位的解答
1.把Button1.Enabled:=False之后试了一下,任然报错,我觉得不像是重入的问题,因为只要我删除了Application.ProcessMessages,则一切都正常。
2.事物过大,我试过开事物SQLITE可以一次插入10万,也没出现这样的问题。
3.自己觉得应该是Application.ProcessMessages与SQLITE事物之间有什么冲突一样。
我提交事物是在点击Application.MessageBox的对话框处,请老老师们帮忙看看。
sundayzhao 2011-02-13
  • 打赏
  • 举报
回复
增加一个变量Flag

调用前flag:=False ;即可防止重入;

procedure TForm2.Button1Click(Sender: TObject);
var
if Flag then Exit;
try
你自己的代码
finally
Flag:=False;
end;
end;


但我觉得你事物开启了,提交了吗,如果每次2500条出现错误,我觉得应该事物太大的原因,可以把一个大事物拆成若干个小事物一般就可以了。
liangpei2008 2011-02-13
  • 打赏
  • 举报
回复
要想界面不出现假死,就把过程放在线程中,在OnTerminate是通知一下主窗体即可
liangpei2008 2011-02-13
  • 打赏
  • 举报
回复
二楼分析的有道理,可能是过程重入
虽然LZ没贴错误信息,但感觉是在过程执行过程中多点了几次按钮导致的.
最好在过程开始时Disable了按钮,结束后Enable.
否则被重入后会破坏过程的数据(堆与栈)
bdmh 2011-02-13
  • 打赏
  • 举报
回复
你用其他数据库试试
LIIJIE1986 2011-02-13
  • 打赏
  • 举报
回复
还有个问题,就是SQLITE对很多其他数据库的特性都不支持,所以我只好把一些数据的检查,放在了程序里面,看起来很冗繁,请老师们帮忙看下,给点思路,看能不能简化一下,谢谢,小弟初学,见笑了。
LIIJIE1986 2011-02-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 lovemit 的回复:]
Application.ProcessMessages;

在一个For循环里你使用了两次Application.ProcessMessages,删除一开始那个试试
[/Quote]
,感谢帮助,晚上的时候我仔细的检查了一下,确定只有一个Application.ProcessMessages的情况下。每次导入的记录只要超过2500条。系统就报错。
多一条都不行,检查了很久,也没看出那里有错误
manfeng 2011-02-13
  • 打赏
  • 举报
回复
确实没什么必要连续用两次Application.ProcessMessages,其实这两个Application.ProcessMessages是连续运行的。不过你说的错误我觉得和这个无关,很可能是运行得太久,楼主在多次按了Button1,结果在执行Application.ProcessMessages时候出现Button1Click这个过程重入。
Mit1208 2011-02-13
  • 打赏
  • 举报
回复
Application.ProcessMessages;

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

2,507

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧