多线程delphi数据库查询

根据设计,Delphi应用程序在一个线程中运行。为了加速应用程序的某些部分,您可能需要决定在Delphi应用程序中添加几个同时执行的路径。...

根据设计,Delphi应用程序在一个线程中运行。为了加速应用程序的某些部分,您可能需要决定在Delphi应用程序中添加几个同时执行的路径。

Multithreaded Database Queries in Delphi Multithreaded Database Queries in Delphi

数据库应用程序中的多线程

在大多数情况下,使用Delphi创建的数据库应用程序都是单线程的——在获取另一组数据之前,对数据库运行的查询需要完成(查询结果的处理)。

为了加快数据处理,例如,从数据库获取数据以创建报告,您可以添加额外的线程来获取和操作结果(记录集)。

继续阅读以了解多线程ADO数据库查询中的3个陷阱:

  1. 解决:“未调用协同初始化”。
  2. 解决:“画布不允许绘制”。
  3. 无法使用主TADoConnection!

客户订单场景

在客户下包含项目的订单的众所周知的场景中,您可能需要显示特定客户的所有订单以及每个订单的项目总数。

在“普通”单线程应用程序中,您需要运行查询以获取数据,然后在记录集上迭代以显示数据。

如果要为多个客户运行此操作,则需要为每个选定客户依次运行此过程。

在多线程场景中,您可以在单独的线程中为每个选定客户运行数据库查询,从而使代码执行速度提高几倍。

dbgo中的多线程(ado)

假设您希望在Delphi列表框控件中显示3个选定客户的订单。

type TCalcThread = class(TThread)    private procedure RefreshCount;    protected procedure Execute; override;    public ConnStr : widestring; SQLString : widestring; ListBox : TListBox; Priority: TThreadPriority; TicksLabel : TLabel; Ticks : Cardinal; end;

这是自定义线程类的接口部分,我们将使用它来获取和操作选定客户的所有订单。

每个订单在列表框控件(列表框字段)中显示为一个项目。ConnStr字段保存ADO连接字符串。TicksLabel保存对TLabel控件的引用,该控件将用于显示同步过程中的线程执行时间。

RunThread过程创建并运行TcalThread线程类的实例。

function TADOThreadedForm.RunThread(SQLString: widestring; LB:TListBox; Priority: TThreadPriority; lbl : TLabel): TCalcThread; var CalcThread : TCalcThread; begin CalcThread := TCalcThread.Create(true) ; CalcThread.FreeOnTerminate := true; CalcThread.ConnStr := ADOConnection1.ConnectionString; CalcThread.SQLString := SQLString; CalcThread.ListBox := LB; CalcThread.Priority := Priority; CalcThread.TicksLabel := lbl; CalcThread.OnTerminate := ThreadTerminated; CalcThread.Resume; Result := CalcThread; end;

从下拉框中选择3个客户后,我们将创建CalcThread的3个实例:

var s, sg: widestring; c1, c2, c3 : integer; begin s := ' SELECT O.SaleDate, MAX(I.ItemNo) AS ItemCount ' + ' FROM Customer C, Orders O, Items I ' + ' WHERE C.CustNo = O.CustNo AND I.OrderNo = O.OrderNo ' ; sg := ' GROUP BY O.SaleDate '; c1 := Integer(ComboBox1.Items.Objects[ComboBox1.ItemIndex]) ; c2 := Integer(ComboBox2.Items.Objects[ComboBox2.ItemIndex]) ; c3 := Integer(ComboBox3.Items.Objects[ComboBox3.ItemIndex]) ; Caption := ''; ct1 := RunThread(Format('%s AND C.CustNo = %d %s',[s, c1, sg]), lbCustomer1, tpTimeCritical, lblCustomer1) ; ct2 := RunThread(Format('%s AND C.CustNo = %d %s',[s, c2, sg]), lbCustomer2, tpNormal,lblCustomer2) ; ct3 := RunThread(Format('%s AND C.CustNo = %d %s',[s, c3, sg]), lbCustomer3, tpLowest, lblCustomer3) ; end;

多线程ado查询的陷阱和技巧

主代码位于线程的Execute方法中:

procedure TCalcThread.Execute; var Qry : TADOQuery; k : integer; begin    inherited;   CoInitialize(nil) ; //CoInitialize was not called Qry := TADOQuery.Create(nil) ;    try// MUST USE OWN CONNECTION // Qry.Connection := Form1.ADOConnection1; Qry.ConnectionString := ConnStr; Qry.CursorLocation := clUseServer; Qry.LockType := ltReadOnly; Qry.CursorType := ctOpenForwardOnly; Qry.SQL.Text := SQLString; Qry.Open; while NOT Qry.Eof and NOT Terminated do begin ListBox.Items.Insert(0, Format('%s - %d', [Qry.Fields[0].asString,Qry.Fields[1].AsInteger])) ; //Canvas Does NOT Allow Drawing if not called through Synchronize Synchronize(RefreshCount) ; Qry.Next; end;    finally Qry.Free; end; CoUninitialize() ; end;

创建多线程Delphi ADO数据库应用程序时,您需要知道如何解决3个陷阱:

  1. 在使用任何dbGo对象之前,必须手动调用CoInitialize和CoUninitialize。未能调用CoInitialize将导致“CoInitialize未调用”异常。CoInitialize方法初始化当前线程上的COM库。ADO是COM。
  2. 您*不能*使用主线程(应用程序)中的TADOConnect对象。每个线程都需要创建自己的数据库连接。
  3. 必须使用同步过程与主线程“对话”,并访问主窗体上的任何控件。

  • 发表于 2021-10-13 10:33
  • 阅读 ( 130 )
  • 分类:数学

你可能感兴趣的文章

数据库上下文(dbcontext)和对象上下文(objectcontext)的区别

...是核心实体框架API的一部分,它允许使用强类型实体类对数据库执行操作。 通常,有必要将应用程序与数据库连接起来。程序员可以用任何编程语言开发应用程序。尽管大多数编程语言为库提供了与数据库交互的方法,但这可...

  • 发布于 2021-07-01 22:51
  • 阅读 ( 176 )

用delphi创建、解析和操作xml文档

...HTML那样是固定格式。 将每个XML文件视为一个自包含的数据库。标记——XML文档中的标记,用尖括号隔开——描绘记录和字段。标记之间的文本是数据。用户使用解析器和解析器公开的一组对象执行诸如检索、更新和插入XML数...

  • 发布于 2021-09-06 15:05
  • 阅读 ( 167 )

如何将媒体文件嵌入delphi可执行文件(rc/.res)(embed media files into a delphi executable (rc/.res))

...可能性是无穷无尽的:exe中的HTML、exe中的exe、exe中的空数据库,等等。

  • 发布于 2021-09-06 15:08
  • 阅读 ( 198 )

使用delphi的键入文件文件创建数据库

简单地说,文件是某种类型的二进制序列。在Delphi中,有三类文件:类型化、文本和非类型化。类型化文件是包含特定类型数据的文件,例如双精度、整数或以前定义的自定义记录类型。文本文件包含可读的ASCII字符。当我们想...

  • 发布于 2021-09-06 15:11
  • 阅读 ( 178 )

了解delphi编程的基础知识

...们还将介绍一些最常见逻辑错误的解决方案。 表格和数据库 在几乎每个Delphi应用程序中,我们都使用表单向用户显示和检索信息。Delphi为我们提供了一系列丰富的可视化工具,用于创建表单并确定其属性和行为。我们可以在...

  • 发布于 2021-09-06 15:13
  • 阅读 ( 190 )

程序退出时delphi中的内存泄漏通知

自Delphi 2006以来的所有Delphi版本都有一个更新的内存管理器,该管理器速度更快,功能更丰富。 “新”内存管理器最出色的功能之一是允许应用程序注册(和注销)预期内存泄漏,并在程序关闭时报告意外内存泄漏。 使用De...

  • 发布于 2021-09-06 15:15
  • 阅读 ( 171 )

delphi中的sql

...化查询语言)是一种标准化的语言,用于定义和操作关系数据库中的数据。根据数据的关系模型,数据库被视为一组表,关系由表中的值表示,通过指定可从一个或多个基表派生的结果表来检索数据。查询采用命令语言的形式,...

  • 发布于 2021-09-08 10:40
  • 阅读 ( 190 )

德尔福单元剖析(德尔福初学者版)

如果您打算成为一名优秀的Delphi程序员,那么“接口”、“实现”和“使用”等词需要在您的编程知识中占有特殊的位置。 德尔福项目 当我们创建一个Delphi应用程序时,我们可以从一个空白项目、一个现有项目或Delphi的一...

  • 发布于 2021-09-10 20:53
  • 阅读 ( 185 )

如何自定义dbnavigator(customize the dbnavigator)

...是一个很好的组件,它提供了一个类似VCR的界面,用于在数据库应用程序中导航数据和管理记录。记录导航由第一个、下一个、上一个和最后一个按钮提供。记录管理由编辑、发布、取消、删除、插入和刷新按钮提供。在一个组...

  • 发布于 2021-09-10 22:21
  • 阅读 ( 223 )

如何delphidbgrid中的multiselect(multiselect in the delphi dbgrid)

Delphi的DBGrid是数据库相关应用程序中使用最广泛的DB感知组件之一。它的主要目的是使应用程序的用户能够在表格网格中操作数据集中的记录。 DBGrid组件的一个鲜为人知的特性是,可以将其设置为允许多行选择。这意味着用...

  • 发布于 2021-09-10 22:29
  • 阅读 ( 195 )

相关推荐