DELPHI线程例子-FC

{优秀的数据库应用应当充分考虑数据库访问的速度问题。通常可以通过优化数据库、优化 查询语句、分页查询等途径收到明显的效果。即使是这样,也不可避免地会在查询时闪现一个带有 SQL符号的沙漏,即鼠标变成了查询等待。最可怜的是用户,他(她)在此时只能无奈地等待。遇到急性子的,干脆在此时尝试 Windows中的其它应用程序,结果致使你的数据库应用显示一大片白色的窗口。真是无奈! 

本文将以简单的例子告诉你如何实现线程查询。还等什么,赶快打开Delphi对照着下面的完整源代码试试吧。 

在查询时能够做别的事情或者取消查询,这只是基本的线程查询,在你阅读了Delphi有关线程帮助之后能立刻实现。这里介绍的是多个线程查询的同步进行。 

在Delphi数据库应用中,都有一个缺省的数据库会话 Session。通常情况下,每个数据库应用中只有这一个会话。无论是查询函数修改数据,在同一时间内只能进行其中的一件事情, 而且进行这一件事情的时候应用程序不能响应键盘、鼠标以及其它的 Windows消息。这就是在 窗口区域会显示一片空白的原因所在。当然,只要将查询或数据操纵构造成线程对象,情况会好一些,至少可以接受窗口消息,也可以随时终止查询或数据操纵,而不会在屏幕上显示出太难看的白色。不过,这只是解决了问题的一部分。假如在进行一个线程查询的时候,用户通过 按钮或菜单又发出了另一个查询的命令,这可如何是好,难道终止正在执行的数据库访问吗? 解决之道就是:多线程同步查询。 

实现多线程同步查询的基本思想是,为每一个查询组件(如TQuery组件)创建一个独占的 数据库会话,然后各自进行数据库访问。需要特别注意的是,因为Delphi中的 VCL组件大多都 不是线程安全的,所以应当在线程查询结束后再将DataSource组件与查询组件关联,从而显示 在DBGrid组件中。 

下面的例子只实现了静态的线程同步查询,即线程对象是固定的,并随窗体的创建和销毁 而创建和销毁。你可以就此进行改进,为每一个数据查询或数据操纵命令创建一个单独的线程对象,从而达到多线程同步查询的目的。 

注意:应用程序中的线程不是越多越好,因为线程将严重吞噬CPU资源,尽管看上去并不明显。谨慎创建和销毁线程将避免你的应用程序导致系统资源崩溃。 

下面的例子给出了同时进行的两个线程查询。第一次按下按钮时,线程开始执行;以后每次按下按钮时,如果线程处于挂起状态则继续执行,否则挂起线程;线程执行完毕之后将连接 DataSource,查询结果将显示在相应的DBGrid中。
} 

{ 这里的多线程同步查询演示程序仅包括一个工程文件和一个单元文件 }
{ 窗体中放置的组件有: }
{ 两个Session组件 }
{ 两个Database组件 }
{ 两个Query组件 }
{ 两个DataSource组件 }
{ 两个DBGrid组件 }
{ 一个Button组件 }
{ 除非特别说明,否则上述各组件的属性都取默认值(见各组件注释) }
{ 对于Database组件,就和一般设置一样,有一个正确的连接即可 }
{ 对于Query 组件,需要在各自的属性 SQL中添加一些查询语句,为了 }
{ 看得更清除,建议不要在两个Query 组件中填写相同的查询语句。 } 

unit Unit1; 

interface 

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, DBTables, Grids, DBGrids, StdCtrls; 

type
TForm1 = class(TForm)
Session1: TSession; { 属性SessionName填写为S1 }
Database1: TDatabase; { 属性SessionName选择为S1 }
Query1: TQuery;{ 属性Database选择为Database1;属性SessionName选择为S1 }
DataSource1: TDataSource; { 属性DataSet设置为空 }
DBGrid1: TDBGrid; { 属性DataSource选择为DataSource1 }
Session2: TSession; { 属性SessionName填写为S2 }
Database2: TDatabase; { 属性SessionName选择为S2 }
Query2: TQuery;{ 属性Database选择为Database2;属性SessionName选择为S2 }
DataSource2: TDataSource; { 属性DataSet设置为空 }
DBGrid2: TDBGrid; { 属性DataSource选择为DataSource2 }
BtnGoPause: TButton; { 用于执行和挂起线程 }
procedure FormCreate(Sender: TObject); { 创建窗体时创建线程对象 }
procedure FormDestroy(Sender: TObject); { 销毁窗体时销毁线程对象 }
procedure BtnGoPauseClick(Sender: TObject); { 执行线程和挂起线程 }
private
public
end; 

TThreadQuery = class(TThread) { 声明线程类 }
private
FQuery: TQuery; { 线程中的查询组件 }
FDataSource: TDataSource; { 与查询组件相关的数据感知组件 }
procedure ConnectDataSource;{ 连接数据查询组件和数据感知组件的方法 }
protected
procedure Execute; override;{ 执行线程的方法 }
public
constructor Create(Query: TQuery;
DataSource: TDataSource); virtual; { 线程构造器 }
end; 

var
Form1: TForm1;
Q1, { 线程查询对象1 }
Q2: TThreadQuery; { 线程查询对象2 } 

implementation 

{$R *.DFM} 

{ TThreadQuery类的实现 } 

{ 连接数据查询组件和数据感知组件}
procedure TThreadQuery.ConnectDataSource;
begin
FDataSource.DataSet := FQuery;{ 该方法在查询结束后才调用 }
end; 

procedure TThreadQuery.Execute;{ 执行线程的方法 }
begin
try
FQuery.Open; { 打开查询 }
Synchronize(ConnectDataSource);{ 线程同步 }
except
ShowMessage(‘Query Error‘); { 线程异常 }
end;
end; 

{ 线程查询类的构造器 }
constructor TThreadQuery.Create(Query: TQuery; DataSource: TDataSource);
begin
FQuery := Query;
FDataSource := DataSource;
inherited Create(True);
FreeOnTerminate := False;
end; 

{ 创建窗体时创建线程查询对象 }
procedure TForm1.FormCreate(Sender: TObject);
begin
Q1 := TThreadQuery.Create(Query1, DataSource1);
Q2 := TThreadQuery.Create(Query2, DataSource2);
end; 

{ 销毁窗体时销毁线程查询对象 }
procedure TForm1.FormDestroy(Sender: TObject);
begin
Q1.Terminate; { 销毁之前终止线程执行 }
Q1.Destroy;
Q2.Terminate; { 销毁之前终止线程执行 }
Q2.Destroy;
end; 

{ 开始线程、继续执行线程、挂起线程 }
procedure TForm1.BtnGoPauseClick(Sender: TObject);
begin
if Q1.Suspended then Q1.Resume else Q1.Suspend;
if Q2.Suspended then Q2.Resume else Q2.Suspend;
end; 

end. 
时间: 2024-10-11 00:56:47

DELPHI线程例子-FC的相关文章

delphi 线程教学第六节:TList与泛型

第六节: TList 与泛型 TList 是一个重要的容器,用途广泛,配合泛型,更是如虎添翼. 我们先来改进一下带泛型的 TList 基类,以便以后使用. 本例源码下载(delphi XE8版本): FooList.Zip unit uFooList; interface uses   Generics.Collections; type   TFooList <T>= class(TList<T>)   private     procedure FreeAllItems;   

多线程的基本概念和Delphi线程对象Tthread介绍

多线程的基本概念和Delphi线程对象Tthread介绍 作者:xiaoru WIN 98/NT/2000/XP是个多任务操作系统,也就是:一个进程可以划分为多个线程,每个线程轮流占用CPU运行时间和资源,或者说,把CPU 时间划成片,每个片分给不同的线程,这样,每个线程轮流的“挂起”和“唤醒”,由于时间片很小,给人的感觉是同时运行的. 多线程带来如下好处: 1)避免瓶颈: 2)并行操作: 3)提高效率:多线程的两个概念: 1) 进程:也称任务,程序载入内存,并分配资源,称为“一个进程”. 注意

4个线程例子,2个线程对同一数字加法运算另外2个线程对同一共享数字减法运算

package com.saic.grape.controller; public class Data { private int j = 0; /** * 加法 */ public synchronized void inc() { j++; System.out.println("inc 加法运算>>" + j); } /** * 减法 */ public synchronized void dec() { j--; System.out.println("

TMsgThread, TCommThread -- 在delphi线程中实现消息循环(105篇博客,好多研究消息的文章)

在delphi线程中实现消息循环 在delphi线程中实现消息循环 Delphi的TThread类使用很方便,但是有时候我们需要在线程类中使用消息循环,delphi没有提供. 花了两天的事件研究了一下win32的消息系统,写了一个线程内消息循环的测试. 但是没有具体应用过,贴出来给有这方面需求的DFW参考一下.希望大家和我讨论. {----------------------------------------------------------------------------- Unit

java线程例子登山

Through its implementation, this project will familiarize you with the creation and execution of threads, and with the use of the Thread class methods. In order to synchronize the threads you will have to use (when necessary), run( ), start( ), curre

在delphi线程中实现消息循环

http://delphi.cjcsoft.net//viewthread.php?tid=635 在delphi线程中实现消息循环 Delphi的TThread类使用很方便,但是有时候我们需要在线程类中使用消息循环,delphi没有提供. 花了两天的事件研究了一下win32的消息系统,写了一个线程内消息循环的测试. 但是没有具体应用过,贴出来给有这方面需求的DFW参考一下.希望大家和我讨论. {--------------------------------------------------

Delphi 简单线程例子

unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; Edit2: TEdit; procedure Button1Click(Sender: TObject); private { Priva

Delphi线程类 DIY(把类指针作为参数传进去,就可以执行类里面的方法啦)

Delphi 封装了一个很强大的线程类 TThread, 我们也自己动手制作一个简单的线程类 首先Type一个类 [delphi] view plain copy type TwwThread = class constructor Create; overload; destructor Destroy; override; private m_hThread: THandle;     //线程 m_ThreadID : TThreadID; public procedure Execute

Delphi线程的终止

当线程对象的Execute()执行完毕的时候,我们就认为此线程终止了.这时候,它会调用Delphi的一个标准例程EndThread(),这个例程再调用API函数ExitThread().由ExitThread()来清除线程所占用的栈. 当结束使用TThread对象的时候,应该确保已经把这个Object Pascal对象从内存中清除了.这才能确保所有内存占有都释放掉,尽管在进程终止时候会自动清除所有的线程对象,但是及时清除已经不再使用的对象,可以使内存的使用效率提高.利用将FreeOnTermin