下面是 定时检查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;
....

解决方案 »

  1.   

    你还没弄明白线程如何去做,一般不用调用ADOCmd.Execute; 在线程创建后,会自动执行Execute,如果程序中代码调用ADOCmd.Execute; 就跟调用普通接口一样,根本不是线程
      

  2.   

    你的问题可能在于你的ADO哪个控件是在外面传递进来的吧。直接在线程里面创建连接控件试试。
      

  3.   

    synchronize(ExecSql);// 这个在你的主线程里执行,导致程序没响应
      

  4.   

    synchronize这个由主线程执行,当然假死。
    把连接的过程放到这个的外面
      

  5.   

    这个过程不是在主线程里执行的,是在线程Execute执行的
      

  6.   

    他是告诉你,这样子执行会跑到主线程当中用主线程的CPU时间去执行,而子线程只是等待主线程执行ExecSQL结束。
      

  7.   


    synchronize相当于整个程序都在一个线程中执行了,除非是线程不安全的组件,一般别用这个函数。
      

  8.   


    //线程类
    //你的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;
      

  9.   

    我个人觉得,如果采用同步连接,而不采用异步连接,任何线程检测代码都是无效的。原因主要有两个:(同步连接时)1. ADOConnection的Open方法会阻塞主线程,它会一直等待原生ADO Connection Object的返回结果,期间将造成主线程的Application无法处理Windows消息,从而造成界面无法刷新。一般当连接超时的时候(取决于ConnectionTimeout)才会抛出异常。2. 如果我们创建了类似与TCheckConnection的检测线程,那线程里面包含的ADOConnection应该是另外创建的,但这样的话即使这个Connection能连通也不能代表那个系统的ADOConnection连接是OK的。(因为这个连接可能因为长时间没有操作,被服务端断掉了)。退一步说,如果连接出错的话,你打算怎么处理?是不是要同步到主线程里面去操作?(比如显示提示界面等等),但这个时候主线程可能已经阻塞了,根本没有办法显示窗体、处理消息。