下面是 定时检查ADO 一个线程。 问题是当检测到连接失败的时候,ADOCommand 会10几秒钟才返回, 在此过程中主程序界面也有 10 几秒钟的不能动像死机一样。 既然用线程就是不希望这个等待会影响到主界面的其他功能使用,是什么原因呢? 或者定时检查ADO 链接是否正常有其他的办法? Timeout 已经设置很小也一样要10几秒钟type
TaCheckConnection = class(TThread)
private
{ Private declarations }
AdoCmd : TADOCommand; //用来执行简单SQl命令,执行成功证明链接正常
ADOCONN2 : TADOConnection;
MsgHandle : THandle;
fIsConnected : Boolean;
protected
procedure Execute; override;
procedure ExecSql; //执行SQL语句过程
public
property IsConnected : Boolean read fIsConnected;
constructor Create(aHandle: THandle);
destructor Destroy;
end;implementation
....
procedure TaCheckConnection.ExecSql;
begin
try
with ADOCmd do
begin
ADOCmd.CommandText := 'SELECT GETDATE()';
ADOCmd.Execute;
end;
fIsConnected := True;
except
on e : Exception do
begin
fIsConnected := False;
end;
end;
end;procedure TaCheckConnection.Execute;
var
waitevent: THandle;
Interval: Cardinal;
begin
{ Place thread code here }
waitevent := CreateEvent(nil, false, false, nil);
interval := 5000;
while not terminated do
begin
synchronize(ExecSql); // *** 如果链接断掉的是后 此处执行需要 10几秒钟返回 ,主界面也10几秒钟不能动。
if not IsConnected then
MessageBox(MsgHandle, '数据库连接中断,请重新链接数据库', '提示', MB_OK);
waitforsingleobject(waitevent, interval);
end;
closehandle(waitevent);
end;
....
TaCheckConnection = class(TThread)
private
{ Private declarations }
AdoCmd : TADOCommand; //用来执行简单SQl命令,执行成功证明链接正常
ADOCONN2 : TADOConnection;
MsgHandle : THandle;
fIsConnected : Boolean;
protected
procedure Execute; override;
procedure ExecSql; //执行SQL语句过程
public
property IsConnected : Boolean read fIsConnected;
constructor Create(aHandle: THandle);
destructor Destroy;
end;implementation
....
procedure TaCheckConnection.ExecSql;
begin
try
with ADOCmd do
begin
ADOCmd.CommandText := 'SELECT GETDATE()';
ADOCmd.Execute;
end;
fIsConnected := True;
except
on e : Exception do
begin
fIsConnected := False;
end;
end;
end;procedure TaCheckConnection.Execute;
var
waitevent: THandle;
Interval: Cardinal;
begin
{ Place thread code here }
waitevent := CreateEvent(nil, false, false, nil);
interval := 5000;
while not terminated do
begin
synchronize(ExecSql); // *** 如果链接断掉的是后 此处执行需要 10几秒钟返回 ,主界面也10几秒钟不能动。
if not IsConnected then
MessageBox(MsgHandle, '数据库连接中断,请重新链接数据库', '提示', MB_OK);
waitforsingleobject(waitevent, interval);
end;
closehandle(waitevent);
end;
....
把连接的过程放到这个的外面
synchronize相当于整个程序都在一个线程中执行了,除非是线程不安全的组件,一般别用这个函数。
//线程类
//你的ExecSql方法说白了效果等效于在主线程中做的SQL查询!
//我这个是刚写的,可能有些bug,你参考一下
unit Unit2;interfaceuses
Classes,ADODb,ActiveX,SyncObjs;type
TCheckConnection = class(TThread)
private
FConnection: TADOConnection;
FInterval:Integer;
FIsConnected:boolean;
FSql: string;
procedure SetConnection(const Value: TADOConnection);
procedure SetSql(const Value: string);
Function ExecuteSql(sql: string): Boolean; protected
procedure Execute; override;
public
Constructor Create(CreateSuspended: Boolean );
Destructor Destroy;override;
property Connection: TADOConnection read FConnection write SetConnection;
property Sql: string read FSql write SetSql;
property Interval:Integer read FInterval write FInterval;
property IsConnected:Boolean read FIsConnected;
end;
procedure NotifyAllThreadsToQuit;var
QuitEvent: TEvent;implementationprocedure NotifyAllThreadsToQuit;
begin
QuitEvent.SetEvent;
end;constructor TCheckConnection.Create(CreateSuspended: Boolean);
begin
Inherited Create(CreateSuspended);
FSql:='';
FInterval:=5000;
FIsConnected:=False;
end;destructor TCheckConnection.Destroy;
begin inherited;
end;procedure TCheckConnection.Execute;
begin
CoInitialize(Nil);
try
FreeOnTerminate:=False;
while not Terminated do
begin
try
ExecuteSql(FSql);
FIsConnected:=True;
except
FIsConnected:=False;
end; case QuitEvent.WaitFor(FInterval) of
wrSignaled, wrAbandoned: Terminate;
wrTimeOut, wrError: ; // do nothing
end;
end;
finally
CoUninitialize;
end;
end;function TCheckConnection.ExecuteSql(sql: string): Boolean;
begin
FConnection.Execute(sql);end;procedure TCheckConnection.SetConnection(const Value: TADOConnection);
begin
if FConnection <> Value then
begin
FConnection := Value;
end;end;procedure TCheckConnection.SetSql(const Value: string);
begin
if FSql <> Value then
begin
FSql := Value;
end;end;initialization
QuitEvent := TEvent.Create(nil,true,false,'CPSEFileMonitorQuitEvent');finalization
QuitEvent.Free;end.
//主调类
var
t1:TCheckConnection;
begin
T1:=TCheckConnection.Create(True);
T1.Connection:=ADOConnection1;
t1.Sql:= ' SELECT GETDATE() ';
t1.Resume;
end;