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

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

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

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

{主窗体代码}
 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.

{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.

ADO多线程数据库总结的更多相关文章

  1. ADO多线程数据库查询

    {ADO查询多线程单元} unit ADOThread; interface uses Classes,StdCtrls,ADODB; type TADOThread = class(TThread) ...

  2. 【转】Delphi多线程学习(9):多线程数据库查询(ADO)

    原文:http://www.cnblogs.com/djcsch2001/articles/2382559.html ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用 ...

  3. 教程-Delphi多线程数据库查询(ADO)

    ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoIniti ...

  4. Delphi多线程数据库查询(ADO)

    ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoIniti ...

  5. 多线程数据库查询(ADO)

    ADO多线程数据库查询通常会出现3个问题: 1.CoInitialize 没有调用(CoInitialize was not called):所以,在使用任何dbGo对象前,必须手 调用CoIniti ...

  6. android 多线程数据库读写分析与优化

    最新需要给软件做数据库读写方面的优化,之前无论读写,都是用一个 SQLiteOpenHelper.getWriteableDataBase() 来操作数据库,现在需要多线程并发读写,项目用的是2.2的 ...

  7. 用ADO操作数据库的方法步骤(ZT)

    http://www.cppblog.com/changshoumeng/articles/113437.html 学习ADO时总结的一些经验 用ADO操作数据库的方法步骤 ADO接口简介 ADO库包 ...

  8. ADO.Net 数据库 删除

    删除数据库里的信息和之前增加,修改大同小异,其写法更加简单,也是把SQL语句写为删除语句 删除一条数据,只需要获取并接收到这条数据唯一的能够代表这条数据的信息,比如主键 代码演示: using Sys ...

  9. ADO.Net 数据库修改

    数据库的修改方法和增加一样,只是把增加语句换成了修改语句,后面执行语句是相同的 首先也是需要获取并接收输入的要修改的哪个数据以及修改后的数据 代码演示: using System; using Sys ...

随机推荐

  1. Linux下ip地址查询

    [时间:2016-12] [状态:Open] [关键词:linux,ip地址,ifconfig,ip addr] 0 引用 说起来比较搞笑,我在windows下知道可以使用ipconfig命令查询本机 ...

  2. 5. BERT算法原理解析

    1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...

  3. java框架篇---hibernate之缓存机制

    一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数 ...

  4. java框架篇---Struts2 本地化/国际化(i18n)

    国际化(i18n)是规划和实施的产品和服务,使他们能很容易地适应特定的本地语言和文化的过程中,这个过程被称为本地化.国际化的过程有时也被称为翻译或本地化启用.国际化是缩写i18n,因为我和两端用n字打 ...

  5. MySQL数据库远程访问权限如何打开(两种方法)

    在我们使用mysql数据库时,有时我们的程序与数据库不在同一机器上,这时我们需要远程访问数据库.缺省状态下,mysql的用户没有远程访问的权限. 下面介绍两种方法,解决这一问题. 1.改表法 可能是你 ...

  6. Python 函数(可变参数)

    在python函数中,可以定义可变参数,顾名思义,可变参数就是,传入的参数是可变的例如,给定一组数字a,b,c...  请计算a2 + b2 + c2 + …… 要定义出这个函数,我们必须确定输入的参 ...

  7. 总结一下搭建简单Web服务器的一些方法

    使用nodejs+anywhere模块搭建静态文件服务器 anywhere随时随地将你的当前目录变成一个静态文件服务器的根目录. 安装npm install anywhere -g,然后进入任意目录在 ...

  8. Linux/Centos下使用mtr做路由图进行网络分析

    工具作用: mtr可以做路由图供我们分析哪里出现故障或者是否存在有网络拥塞的情况 1. 首先安装mtr 工具 使用yum  安装 :  yum  install mtr -y  2. 使用 我经常在工 ...

  9. [Object Tracking] Contour Detection through Tensorflow running on smartphone

    From: 手机端运行卷积神经网络的一次实践 -- 基于 TensorFlow 和 OpenCV 实现文档检测功能 貌似不错的东西:移动端视觉识别模型:MobileNets Holistically- ...

  10. 九度OJ 1067 n的阶乘 (模拟)

    题目1067:n的阶乘 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5666 解决:2141 题目描写叙述: 输入一个整数n,输出n的阶乘 输入: 一个整数n(1<=n<=2 ...