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

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

    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 FilesCommon FilesCodeGear SharedData目录下有一个dbdemos.mdb文件,用来作为测试的例子。dbdemos.mdb中的customer表保存了客户信息,orders表中保存了订单信息。

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

    4、COM接口调用时必须有线程自己的接口。

        如:在A线程建的COM接口,B线程调用时就提示“应用程序调用一个已为另一线程整理的接口”。这时只要在B线程建立自己独有的COM接口使用就可以了。

     1 {主窗体代码}
     2 unit Main;
     3 interface
     4   uses Windows, Messages, SysUtils, Variants,
     5     Classes, Graphics, Controls, Forms, Dialogs, DB, ADODB, StdCtrls;
     6 type
     7   TForm2 = class(TForm)
     8   ComboBox1: TComboBox;
     9   ComboBox2: TComboBox;
    10   ComboBox3: TComboBox;
    11   ListBox1: TListBox;
    12   ListBox2: TListBox;
    13   ListBox3: TListBox;
    14   Button1: TButton;
    15   ADOConnection1: TADOConnection;
    16   ADOQuery1: TADOQuery; 
    17   Label1: TLabel;
    18   Label2: TLabel;
    19   Label3: TLabel;
    20   procedure FormCreate(Sender: TObject); 
    21   procedure Button1Click(Sender: TObject);
    22   private { Private declarations }
    23   public { Public declarations }
    24   end;
    25 var Form2: TForm2;
    26 implementation
    27 uses
    28   ADOThread;
    29   {$R *.dfm}
    30 
    31 procedure TForm2.Button1Click(Sender: TObject);
    32 const 
    33   SQL_CONST='Select SaleDate from orders where CustNo = %d';
    34   var c1,c2,c3:Integer; s1,s2,s3:string;
    35 begin //取得三个选择框客户的编码
    36   c1:=Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]);
    37   c2:=Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]);
    38   c3:=Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]); //生成SQL 查询语句
    39   s1:=Format(SQL_CONST,[c1]);
    40   s2:=Format(SQL_CONST,[c2]);
    41   s3:=Format(SQL_CONST,[c3]); //三个线程同时查询
    42   TADOThread.Create(s1,ListBox1,Label1);
    43   TADOThread.Create(s2,ListBox2,Label2);
    44   TADOThread.Create(s3,ListBox3,Label3);
    45 end;
    46 
    47 procedure TForm2.FormCreate(Sender: TObject);
    48 var
    49   strSQL:string;
    50 begin
    51   strSQL:='SELECT CustNo,Company FROM customer';
    52   ADOQuery1.Close;
    53   ADOQuery1.SQL.Clear;
    54   ADOQuery1.SQL.Add(strSQL);
    55   ADOQuery1.Open;
    56   ComboBox1.Clear;
    57   ComboBox2.Clear;
    58   ComboBox3.Clear; //将客户Company和相关CustNo填到ComboBox中
    59   while not ADOQuery1.Eof do
    60   begin
    61     ComboBox1.AddItem(ADOQuery1.Fields[1].asString, TObject(ADOQuery1.Fields[0].AsInteger));
    62     ADOQuery1.Next;
    63   end;
    64   ComboBox2.Items.Assign(ComboBox1.Items);
    65   ComboBox3.Items.Assign(ComboBox1.Items); // 默认选中第一个
    66   ComboBox1.ItemIndex := 0;
    67   ComboBox2.ItemIndex := 0;
    68   ComboBox3.ItemIndex := 0;
    69 end;
    70 end.
     1 {ADO查询多线程单元}
     2 unit ADOThread;
     3 interface
     4 uses
     5   Classes,StdCtrls,ADODB;
     6 type TADOThread = class(TThread)
     7   private { Private declarations }
     8   FListBox:TListBox;
     9   FLabel:TLabel;
    10   ConnString:WideString;
    11   FSQLString:string;
    12   procedure UpdateCount;
    13   protected procedure Execute; override;
    14   public constructor Create(SQL:string;LB:TListBox;Lab:TLabel);
    15 end;
    16 
    17 implementation
    18 uses
    19   Main,SysUtils,ActiveX;
    20   { TADOThread }
    21 
    22 constructor TADOThread.Create(SQL: string; LB: TListBox;Lab:TLabel);
    23 begin
    24   ConnString:=Form2.ADOConnection1.ConnectionString;
    25   FListBox:=LB;
    26   FLabel:=Lab;
    27   FSQLString:=SQL;
    28   Inherited Create(False);
    29 end;
    30 
    31 procedure TADOThread.Execute;
    32 var
    33   Qry:TADOQuery;
    34   i:Integer;
    35 begin { Place thread code here }
    36   FreeOnTerminate:=True;
    37   CoInitialize(nil); //必须调用(需Uses ActiveX)
    38   Qry:=TADOQuery.Create(nil);
    39   try
    40     Qry.ConnectionString:=ConnString; //必须有自己的连接
    41     Qry.Close;
    42     Qry.SQL.Clear;
    43     Qry.SQL.Add(FSQLString);
    44     Qry.Open;
    45     FListBox.Clear;
    46     for i := 0 to 100 do //为了执行久点重复历遍数据集101次
    47     begin
    48       while not Qry.Eof And not Terminated do
    49       begin
    50         FListBox.AddItem(Qry.Fields[0].asstring,nil); //如果不调用Synchronize,会出现Canvas Does NOT Allow Drawing
    51         Synchronize(UpdateCount);
    52         Qry.Next;
    53       end;
    54       Qry.First;
    55       FListBox.AddItem('*******',nil);
    56     end;
    57   finally
    58     Qry.Free;
    59   end;
    60   CoUninitialize;
    61 end;
    62 
    63 procedure TADOThread.UpdateCount;
    64 begin
    65   FLabel.Caption:=IntToStr(FListBox.Items.Count);
    66 end;
    67 end.

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

  • 相关阅读:
    for循环嵌套的原理
    php for循环|求1-100之间被3整除且被5不整除的偶数
    php 1-100之间能被3整除的数字之和;
    php判断某年某月有多少天
    关系运算符
    变量
    习题5-7 使用函数求余弦函数的近似值
    习题5-6 使用函数输出水仙花数
    习题4-11 兔子繁衍问题
    习题4-9 打印菱形图案
  • 原文地址:https://www.cnblogs.com/FKdelphi/p/4654473.html
Copyright © 2011-2022 走看看