【问题标题】:TADOConnection with SQL Server Thread with DelphiTADOConnection 与 SQL Server 线程与 Delphi
【发布时间】:2021-10-07 22:18:54
【问题描述】:

我正在做一个项目,我需要考虑紧急情况。

主要问题是,如何检查数据库是否连接(圆圈对象=红色或绿色)?

BeforeConnectAfterDisconnect,他们没有好的答案。

内部类型:

创建连接:

procedure TForm1.Button1Click(Sender: TObject);
var
  s : String;
begin
  ADOConnectionSQL := TADOConnection.Create(nil);
  ADOConnectionSQL.LoginPrompt := false;
  with ADOSQL do
  begin
    s := 'Provider=SQLNCLI11.1;'+
    'Persist Security Info=False;'+
    'User ID='+Edit1.Text+';'+
    'Initial Catalog='+Edit2.Text+';'+
    'Data Source='+Edit3.Text+';'+
    'Initial File Name="";'+
    'Server SPN="";'+
    'password="'+Edit4.Text+'"';
    ADOConnectionSQL.ConnectionString := s;
  end;
  ADOConnectionSQL.BeforeConnect := SQLConnected;
  ADOConnectionSQL.AfterDisconnect := SQLDisconnected;
end;

尝试连接:

procedure TForm1.Button2Click(Sender: TObject);
var
  Thread : TThread;
begin
  Thread := TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.Synchronize(TThread.CurrentThread,
      procedure
        begin
        try
          ADOConnectionSQL.Connected := True;
          ADOConnectionSQL.Open;
        except
          on E: Exception do
          begin
            ShowMessage('Exception message = '+E.Message);
          end;
        end;
        ADOQuerySQL := TADOQuery.Create(nil);
      end);
    end);
  Thread.OnTerminate := FinishConnected;
  Thread.Start;
end;

绿色或红色:

procedure TForm1.SQLConnected(Sender: TObject);
begin
  Circle1.Fill.Color := $FF00FF00;
end;

procedure TForm1.SQLDisconnected(Sender: TObject);
begin
  Circle1.Fill.Color := $FFFF0000;
end;

完成连接:

procedure TForm1.FinishConnected(Sender: TObject);
begin
  if TThread(Sender).FatalException <> nil then
  begin
    // something went wrong
    ShowMessage ('Failure to connection');
    //Exit;
  end;
end;

当 SQL Server 在线时,我希望看到一个绿色圆圈。当与服务器的连接中断时,圆圈应该是红色的。

【问题讨论】:

    标签: sql multithreading delphi adoconnection


    【解决方案1】:

    您是在主 UI 线程的上下文中创建和打开 ADO 连接,而不是在工作线程的上下文中。所以你的工作线程基本上没用。您可以直接使用TThread.ForceQueue() 来获得相同的效果。

    ADO 在内部使用 COM 技术,因此无论如何您都不能真正跨线程边界使用它。如果要在线程中使用 ADO,请给线程自己的 ADO Connection 和 Query 对象。在线程上下文中执行所有 SQL 工作,并根据需要与主 UI 线程同步状态更新。

    此外,您需要在工作线程中初始化 COM 库,然后才能使用 ADO。

    试试类似的方法:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      Thread : TThread;
      ConnStr: string;
    begin
      ConnStr := 'Provider=SQLNCLI11.1;'+
        'Persist Security Info=False;'+
        'User ID='+Edit1.Text+';'+
        'Initial Catalog='+Edit2.Text+';'+
        'Data Source='+Edit3.Text+';'+
        'Initial File Name="";'+
        'Server SPN="";'+
        'password="'+Edit4.Text+'"';
    
      Thread := TThread.CreateAnonymousThread(
        procedure
        var
          ADOConnectionSQL: TADOConnection;
          ADOQuerySQL: TADOQuery;
        begin
          CoInitialize(nil);
          try
            ADOConnectionSQL := TADOConnection.Create(nil);
            try
              ADOConnectionSQL.LoginPrompt := False;
              ADOConnectionSQL.ConnectionString := ConnStr;
    
              ADOConnectionSQL.Open;
    
              TThread.Queue(nil,
                procedure
                begin
                  Circle1.Fill.Color := TAlphaColorRec.Green;
                end
              );
    
              ADOQuerySQL := TADOQuery.Create(nil);
              try
                ADOQuerySQL.Connection := ADOConnectionSQL;
                // use ADOQuerySQL as needed...
              finally
                ADOQuerySQL.Free;
              end;
            finally
              ADOConnectionSQL.Free;
            end;
          finally
            CoUninitialize;
          end;
        end);
      Thread.OnTerminate := SQLFinished;
      Thread.Start;
    end;
    
    procedure TForm1.SQLFinished(Sender: TObject);
    begin
      Circle1.Fill.Color := TAlphaColorRec.Red;
      if TThread(Sender).FatalException <> nil then
      begin
        // something went wrong
        ShowMessage('Failure! ' + Exception(TThread(Sender).FatalException).Message);
      end;
    end;
    

    【讨论】:

    • 非常感谢,我试过了,可以了。我相信我不是100%清楚。当我尝试连接数据库并且IP错误时,软件将被锁定直到超时完成(您已修复此问题),但我想让圆圈一直保持连接可用,并在连接可用时变为红色下跌降落。也许有一个计时器来解决这个问题。你有什么想法吗?
    • 不需要计时器。我提供的代码将处理您想要的一切。最初只需将圆圈设为红色,因为线程尚未运行。然后,仅当Open() 成功时,线程才会将圆圈设置为绿色,然后在线程因任何原因终止时将其设置回红色。我还建议在创建线程但尚未调用Open() 时添加第三种颜色,例如黄色,以便用户可以看到应用程序正忙于尝试连接。
    猜你喜欢
    • 2010-11-17
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 2012-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多