zoukankan      html  css  js  c++  java
  • Delphi多线程数据库查询(ADO)

    Delphi多线程数据库查询(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 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查询多线程单元}
    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.

    程序运行结果可以看到三个线程同时执行。第一第三两个线程条件一样,查询的结果也一样。

    http://blog.csdn.net/tercel99/article/details/5783593

  • 相关阅读:
    课后作业07--二分法查找算法代码
    检索03 -- 二分法查找
    课堂随笔05--冒泡排序
    课后作业 06 -- 小数后几位精确判断并输出
    课后作业 05 -- 输出一段带字母与数字的随机数
    课后作业 04 --DateTime应用,判断多久后生日之类
    检索02--随机数种子的一些概念和理解
    课堂随笔04--关于string类的一些基本操作
    P1174 互素
    P1001 第K极值
  • 原文地址:https://www.cnblogs.com/findumars/p/5294106.html
Copyright © 2011-2022 走看看