我现在遇到一个问题,我现在在做一个餐饮的服务端,因为使用的是ID卡,所以每次查询余额或者消费的时候都要去连接数据库查询,因为会存在并发处理,比如一个消费事件对上下面N台餐饮机同时触发,所以每次在查询余额或者消费的时候,都是创建一个单独的ADO连接数据库,查询数据或者插入数据这样的操作之后,在事件结束的时候把创建的ADO,free掉,但是现在有个问题不知道怎么解决,就是我这个服务端平时用着都好好的,但是比如用过一周或者几天后,就会自动退出,无报错的自动退出,异常捕获也捕获不到什么,重新打开服务端的话,又可以用几天或者一周,然后再无故退出,不知道各位大大有没有什么好的建议或者有没有遇到类似的情况
解决方案 »
- 如何解决sokcet的stack overflow的问题
- 关于TDBGridEh导出excel表的问题
- DgGridEH的DEMO例子中,标题下面的第一行,是固定的,而且可以有下拉框。是怎么设置呢?
- AdoConnection如何连接excel文件(.xls)????
- 如何成批地创建记录(sql语句)
- 分组统计!
- 求图层控件!
- 请教adoquery查询返回数据集合指针移动方法???
- fastreport如何控制打印分数?(在线)
- 數據集中當前指針的記錄號不是RecNo嗎,為什麼我得到的值總是-1呢,為什麼
- 【新手】 delphi 数据库时间提取
- 使用delphi 7 制做 ribbon 风格的程序,怎样让程序体积小一点?
Try
//'Provider=SQLOLEDB.1;Password=sanxingxtep;Persist Security Info=True;User ID=sa;Initial Catalog=NT_COWA_XTEP2010;Data Source=192.168.3.44'
ADOConnect := TADOConnection.Create(nil);
ADOConnect.LoginPrompt := False;
ADOConnect.ConnectionString := 'Provider=SQLOLEDB.1;Password=zly19811205;Persist Security Info=True;User ID=sa;Initial Catalog=NT_COWA_XTEP2010;Data Source=192.168.0.97';
ADOConnect.CommandTimeout := 1800;
ADOConnect.Connected := True;
ADO_Select := TADOQuery.Create(nil);
ADO_Select.Connection := ADOConnect;
except
on e:exception do
Begin
StrExp := FormatDateTime('yyyy-mm-dd hh:mm:ss',now())+' ADOConnect :'+e.Message+'**ErrorCode:36';
UMainServe.FMainServer.WriteException(StrExp);
CanContinue := False;
ErrorCode :=36;
Exit;
End;
End;
try
//消费事件语句
finally
ADO_Select.Close;
ADO_Select.Free;
ADO_Select.Destroy;
ADOConnect.Connected := False;
ADOConnect.Free;
end;
2 另外建议Lz在try中间加入日志处理,把错误记下来便于差错,还有,别随便只记错误信息,把当前一些控件状态也记下来
3 Lz没有发现那两个创建和释放有点问题么,第一个try except包括了创建,但是如果创建意外,却没有进行处理,反而是在第二个try finally中进行释放,那么假设第一个 try发生意外,程序可不是直接崩了
我有尝试过使用一次性申请的,但是是有多台设备同时触发这个事件操作的,如果用单个ADO,我怕在并发下会报错或者延迟什么的,所以才一直创建新的,还有,您说当前一些控件状态,能告诉我,最好都记忆什么状态么,而且我在程序退出后,要去查错误日志的时候,发现没这个文本,也就是说没采集到
我是说比如
adoconnection或者TADOQuery创建或者链接发生意外,第一个try退出
当执行到你第二个try时,尝试关闭和释放一个空的connection或者adoquery肯定会意外吧,最要命的是,这个意外还是在finally里抛出的,程序可不直接崩溃了么?
还有我所说的状态就是看看你创建的adoconnection和adoquery是否正常链接,是否为空,或者adoqueyr上一次执行的sql语句是什么(可能执行中报错的)等等
我想问下,比如我在程序刚创建的时候,创建了一个adoconnection,然后在消费事件上只创建adoquery,然后该adoquery连接最初创建的adoconnection,这样可以么,当并发的时候,会不会堵塞什么的,就是比如我两个adoquery同时查询的时候,adoconnection是会排先后还是报错,并发数有可能有40多个或者以上的
实际上应该用一个try exception 包起来,意外时加个状态判断就可以了,为空时不考虑,如果不为空则释放
如果抱着程序崩溃就无需释放的心理,你会发现你的机器会越来越慢,这也是程序崩溃的隐患之一另外如果adoquery执行失败,有时候从意外看不出原因的,要看里面的sql语句,建议你在执行查询之外的操作时加上事务处理,因为并发操作会有各种意想不到的问题的,你可以查下begintransaction
LZ可以看下这个,人家的adoquery和connection可不是每次都创建哦
http://hi.baidu.com/plovemxz/blog/item/ae5b7e2825dd17f599250a1d.html
http://topic.csdn.net/t/20020801/07/915061.html
2L的回复
我可以直接在exit前面加一个
FreeAndNil(ADOConnect);
FreeAndNil(ADO_Select);
这样么,不判断是不是Nil的
http://kudick.blog.163.com/blog/static/16660663200931311194482/
ADO_Select.Free;
ADO_Select.Destroy;
发现问题了么?
.close为空时会出错需要判断
.Free;是正确的
.Destroy;这个则是多余的
我知道,正如你所说的,free自身不是就判断是不是nil了么
刚才我说的是,能不能直接在上面的那个try的except 中的exit前面加
FreeAndNil(ADOConnect);
FreeAndNil(ADO_Select);
这个
下面这句会不会出错呢
UMainServe.FMainServer.WriteException(StrExp);这个方法如果抛出异常,外层调用对异常有没有处理呢多记录点日志,就能定位问题了
也不能这样说,以前我做过一个例子,有时候因为网络或者数据库的原因,连接会超时,报意外,而以下的adoquery则跟着意外,总之日志的习惯是好的
另外,执行sql的时候也有可能报异常,因此下面的代码也应该捕获异常
有的,我每次查询都有使用try语句,但是自动退出的时候,都没记录下来
Try
if not assigned(ADOConnect) then //此处可以做成一个单例
ADOConnect := TADOConnection.Create(application); //正常下让adoconnect跟着主程序一起释放
ADOConnect.LoginPrompt := False;
ADOConnect.ConnectionString := 'Provider=SQLOLEDB.1;Password=zly19811205;Persist Security Info=True;User ID=sa;Initial Catalog=NT_COWA_XTEP2010;Data Source=192.168.0.97';
ADOConnect.CommandTimeout := 1800;
ADOConnect.Connected := True;
except
on e:exception do
Begin
freeandnil(ADOConnect);
StrExp := FormatDateTime('yyyy-mm-dd hh:mm:ss',now())+' ADOConnect :'+e.Message+'**ErrorCode:36';
UMainServe.FMainServer.WriteException(StrExp);
CanContinue := False;
ErrorCode :=36;
Exit;
End;
End;
try
ADO_Select := TADOQuery.Create(nil);
ADO_Select.Connection := ADOConnect;
//消费事件语句
finally
freeandnil(ADO_Select);
end;
我想问的是,如果只用一个ADOCONNECTION的话,当并发查询的时候,会不会有影响,我是怕这个才创建那么多个的
运行一段时间后,看一下内存的使用情况,是不是稳定的连续不断的上涨(如果有泄露,一般会把服务器吊死,但自动退出好像不多)
也可以用fastmm,eurakalog(写错了么?)之类的工具看一下有没有内存泄露另外,如果你的服务端是个一般的exe的话,可以再写个守护程序,发现这个程序退出就自动把它启动起来,就象个病毒似的
//'Provider=SQLOLEDB.1;Password=sanxingxtep;Persist Security Info=True;User ID=sa;Initial Catalog=NT_COWA_XTEP2010;Data Source=192.168.3.44'
ADOConnect := TADOConnection.Create(nil);
ADO_Select := TADOQuery.Create(nil);
try
try
ADOConnect.LoginPrompt := False;
ADOConnect.ConnectionString := 'Provider=SQLOLEDB.1;Password=zly19811205;Persist Security Info=True;User ID=sa;Initial Catalog=NT_COWA_XTEP2010;Data Source=192.168.0.97';
ADOConnect.CommandTimeout := 1800;
ADOConnect.Connected := True;
ADO_Select.Connection := ADOConnect;
//消费事件语句
except
on e:exception do
Begin
StrExp := FormatDateTime('yyyy-mm-dd hh:mm:ss',now())+' ADOConnect :'+e.Message+'**ErrorCode:36';
UMainServe.FMainServer.WriteException(StrExp);
CanContinue := False;
ErrorCode :=36;
Exit;
End;
end;
finally
ADO_Select.Close;
ADO_Select.Free;
ADOConnect.Connected := False;
ADOConnect.Free;
end;对象的创建在try外面
对象的销毁在finally里面, 确保一定能被销毁
另外,当一个对象被free掉后,不需要再执行Destroy操作。精简出来的代码结构应该是这样的
object:= TObject.Create;
try
try
object.....;//使用对象
except
//异常时触发的操作
end;
finally
object.free;
end;
对象的销毁在finally里面, 确保一定能被销毁
另外,当一个对象被free掉后,不需要再执行Destroy操作。精简出来的代码结构应该是这样的Delphi(Pascal) code
object:= TObject.Create;
try
try
object.....;//使用对象
except
//异常时触发的操作
end;
finally
object.free;
end;
学习了。
这个非常好。
需要考慮一下丟失更新的問題。