• 多线程数据库查询(ADO)


    ADO多线程数据库查询通常会出现3个问题:

    1、CoInitialize 没有调用(CoInitialize was not called);所以,在使用任何dbGo对象前,必须手 调用CoInitialize和CoUninitialize。调用CoInitialize失败会产生"CoInitialize was not called"例外。

    2、画布不允许绘画(Canvas does not allow drawing);所以,必须通过Synchronize过程来通知主线程访问主窗体上的任何控件。

    3、不能使用主ADO连接(Main TADoConnection cannot be used!);所以,线程中不能使用主线程中TADOConnection对象,每个线程必须创建自己的数据库连接。

         Delphi2007安装后在X:/Program Files/Common Files/CodeGear Shared/Data目录下有一个dbdemos.mdb文件,用来作为测试的例子。dbdemos.mdb中的customer表保存了客户信息,orders表中保存了订单信息。

           测试程序流程大致是这样的:在主窗体上放TADOConnection和TQuery控件,启动时这个TQuery从Customer表中查出客户编码CustNo和公司名称Company,放到三个Combox框中,分别在三个列表框中选定客户公司名称,按照公司名称所对应的客户代码建立三个线程同时在orders表中查询销售日期SaleDate分别填入ListBox中。

     

     

    unit ADOThread;  
       
    interface  
       
    uses  
      Classes,StdCtrls,ADODB;  
       
    type  
      TADOThread = class(TThread)  
      private  
        { Private declarations }  
        FListBox:TListBox;  
        FLabel:TLabel;  
        ConnString:WideString;  
        FSQLString:string;  
        procedure UpdateCount;  
      protected  
        procedure Execute; override;  
      public  
        constructor Create(SQL:string;LB:TListBox;Lab:TLabel);  
      end;  
       
    implementation  
       
    uses Main,SysUtils,ActiveX;  
       
    { TADOThread }  
       
    constructor TADOThread.Create(SQL: string; LB: TListBox;Lab:TLabel);  
    begin  
      ConnString:=Form2.ADOConnection1.ConnectionString;  
      FListBox:=LB;  
      FLabel:=Lab;  
      FSQLString:=SQL;  
      Inherited Create(False);  
    end;  
       
    procedure TADOThread.Execute;  
    var  
      Qry:TADOQuery;  
      i:Integer;  
    begin  
      { Place thread code here }  
      FreeOnTerminate:=True;  
      CoInitialize(nil);  //必须调用(需Uses ActiveX)   
      Qry:=TADOQuery.Create(nil);  
      try  
        Qry.ConnectionString:=ConnString;   //必须有自己的连接   
        Qry.Close;  
        Qry.SQL.Clear;  
        Qry.SQL.Add(FSQLString);  
        Qry.Open;  
        FListBox.Clear;  
        for i := 0 to 100 do  //为了执行久点重复历遍数据集101次   
          begin  
            while not Qry.Eof And not Terminated do  
            begin  
              FListBox.AddItem(Qry.Fields[0].asstring,nil);  
              //如果不调用Synchronize,会出现Canvas Does NOT Allow Drawing   
              Synchronize(UpdateCount);  
              Qry.Next;  
            end;  
            Qry.First;  
            FListBox.AddItem('*******',nil);  
          end;  
      finally  
        Qry.Free;  
      end;  
      CoUninitialize;  
    end;  
       
    procedure TADOThread.UpdateCount;  
    begin  
      FLabel.Caption:=IntToStr(FListBox.Items.Count);  
    end;  
       
    end.  
    

      

    unit Main;  
       
    interface  
       
    uses  
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
      Dialogs, DB, ADODB, StdCtrls;  
       
    type  
      TForm2 = class(TForm)  
        ComboBox1: TComboBox;  
        ComboBox2: TComboBox;  
        ComboBox3: TComboBox;  
        ListBox1: TListBox;  
        ListBox2: TListBox;  
        ListBox3: TListBox;  
        Button1: TButton;  
        ADOConnection1: TADOConnection;  
        ADOQuery1: TADOQuery;  
        Label1: TLabel;  
        Label2: TLabel;  
        Label3: TLabel;  
        procedure FormCreate(Sender: TObject);  
        procedure Button1Click(Sender: TObject);  
      private  
        { Private declarations }  
      public  
        { Public declarations }  
      end;  
       
    var  
      Form2: TForm2;  
       
    implementation  
       
    uses ADOThread;  
       
    {$R *.dfm}  
       
    procedure TForm2.Button1Click(Sender: TObject);  
    const  
      SQL_CONST='Select SaleDate from orders where CustNo = %d';  
    var  
      c1,c2,c3:Integer;  
      s1,s2,s3:string;  
    begin  
      //取得三个选择框客户的编码   
      c1:=Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);  
      c2:=Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]);  
      c3:=Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]);  
      //生成SQL 查询语句   
      s1:=Format(SQL_CONST,[c1]);  
      s2:=Format(SQL_CONST,[c2]);  
      s3:=Format(SQL_CONST,[c3]);  
      //三个线程同时查询   
      TADOThread.Create(s1,ListBox1,Label1);  
      TADOThread.Create(s2,ListBox2,Label2);  
      TADOThread.Create(s3,ListBox3,Label3);  
    end;  
    
    procedure TForm2.FormCreate(Sender: TObject);  
    var  
      strSQL:string;  
    begin  
      strSQL:='SELECT CustNo,Company FROM customer';  
      ADOQuery1.Close;  
      ADOQuery1.SQL.Clear;  
      ADOQuery1.SQL.Add(strSQL);  
      ADOQuery1.Open;  
      ComboBox1.Clear;  
      ComboBox2.Clear;  
      ComboBox3.Clear;  
      //将客户Company和相关CustNo填到ComboBox中   
      while not ADOQuery1.Eof do  
      begin  
        ComboBox1.AddItem(ADOQuery1.Fields[1].asString,  
            TObject(ADOQuery1.Fields[0].AsInteger));  
        ADOQuery1.Next;  
      end;  
      ComboBox2.Items.Assign(ComboBox1.Items);  
      ComboBox3.Items.Assign(ComboBox1.Items);  
      // 默认选中第一个   
      ComboBox1.ItemIndex := 0;  
      ComboBox2.ItemIndex := 0;  
      ComboBox3.ItemIndex := 0;  
    end;  
    
    end.{ADO查询多线程单元}  
    

      

  • 相关阅读:
    mysql replication常见错误整理
    enq: TX
    LOGMNR分析redo log和archive log教程
    使用create datafile... as ...迁移数据文件到裸设备
    mysql无法启动,报错 Can't start server: can't create PID file: No space left on device
    MYSQL 权限设置查询
    ORA-02437 违反主键
    oracle sequence的用法
    sequence有关问题
    关于Relay Log无法自动删除的问题
  • 原文地址:https://www.cnblogs.com/yzryc/p/7651002.html
Copyright © 2020-2023  润新知