讨论多线程和ADO数据查询,我想构建一个类,以后就通过继承来调用。我兴趣的来看看。 ( 积分: 200 )

  • 主题发起人 mystarter
  • 开始时间
M

mystarter

Unregistered / Unconfirmed
GUEST, unregistred user!
我是想先构建TExecSQLThread和TOpenSQLThread类。

在这两个基类中,进行线程执行SQL和打开查询。在创建类时,输入参数ADO的连接字符串与SQL字符串,互斥句柄。(ADOThread.pas)

然后,再建类继承自这基类,实现功能。与主线程同步。
(OutPortUnit.pas,这个单元中实现将数据库数据内容通过TStringList输出到文本中。)

但在procedure TOutPortThread.Execute;中
inherited; //这里好象并没有对FADOQuery进行处理
list.Add(FADOQuery.SQL.Text); //这个地方出现错误,FADOQuery好象并没有创建。

源程序如下:
/////////// 基类 ADOThread.pas
unit ADOThread;

interface

uses
Classes, DB, ADODB, forms,SysUtils,ComCtrls, Windows;

type
TExecSQLThread = class(TThread)
private
FMutex:THandle;
FExecTime:Integer;
FADOConnection: TADOConnection;
FADOQuery: TAdoQuery;
procedure ADOTimeOut;
procedure ADOExecSQL;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean; ConnString,StrSQL:string;hMutex:THandle); overload;
destructor Destroy; override;
end;

type
TOpenSQLThread = class(TThread)
private
FMutex:THandle;
FExecTime:Integer;
FADOConnection: TADOConnection;
FADOQuery: TAdoQuery;
procedure ADOTimeOut;
procedure ADOOpenSQL;
protected
procedure Execute; override;
public

constructor Create(CreateSuspended: Boolean; ConnString,StrSQL:string;hMutex:THandle); overload;
destructor Destroy; override;
end;

implementation

constructor TExecSQLThread.Create(CreateSuspended: Boolean; ConnString,
StrSQL:string;hMutex:THandle);
begin
inherited Create(CreateSuspended);
FADOConnection:= TAdoConnection.Create(Application);
FADOConnection.ConnectionString:=ConnString;
FADOConnection.LoginPrompt:=false;
FADOQuery := TAdoQuery.Create(Application);
FADOQuery.SQL.Add(StrSQL);
FExecTime:=0;
FMutex:=hMutex;
self.FreeOnTerminate:=true; //必须加上,否则不能释放内存
end;

destructor TExecSQLThread.Destroy;
begin
FADOQuery.Close;
FADOQuery.Free;
FADOConnection.Close;
FADOConnection.free;
inherited;
end;

procedure TExecSQLThread.Execute;
begin
if WaitForSingleObject(FMutex, INFINITE) = WAIT_OBJECT_0 then
begin
FADOConnection.Open;
ADOExecSQL;
end;
ReleaseMutex(FMutex);

{ Place thread code here }
end;

procedure TExecSQLThread.ADOExecSQL;
begin
try
FExecTime:=FExecTime+1;
if FExecTime<=3 then FADOQuery.ExecSQL
else Synchronize(ADOTimeOut);
except
ADOExecSQL;
end;
end;

procedure TExecSQLThread.ADOTimeOut;
begin

end;

constructor TOpenSQLThread.Create(CreateSuspended: Boolean; ConnString,
StrSQL:string;hMutex:THandle);
begin
inherited Create(CreateSuspended);
FADOConnection:= TAdoConnection.Create(Application);
FADOConnection.ConnectionString:=ConnString;
FADOConnection.LoginPrompt:=false;
FADOQuery := TAdoQuery.Create(Application);
FADOQuery.Connection:=FADOConnection;
FADOQuery.SQL.Add(StrSQL);
FExecTime:=0;
FMutex:=hMutex;
self.FreeOnTerminate:=true; //必须加上,否则不能释放内存
end;

destructor TOpenSQLThread.Destroy;
begin
FADOQuery.Close;
FADOQuery.Free;
FADOConnection.Close;
FADOConnection.free;
inherited;
end;

procedure TOpenSQLThread.ADOOpenSQL;
begin
try
FExecTime:=FExecTime+1;
if FExecTime<=3 then FADOQuery.Open
else Synchronize(ADOTimeOut);
except
ADOOpenSQL;
end;
end;

procedure TOpenSQLThread.ADOTimeOut;
begin

end;


procedure TOpenSQLThread.Execute;
var
filePath,stemp,lines,tmpstr:string;
j:integer;
begin
if WaitForSingleObject(FMutex, INFINITE) = WAIT_OBJECT_0 then
begin
FADOConnection.Open;
ADOOpenSQL;
end;
ReleaseMutex(FMutex);

{ Place thread code here }
end;


end.



下面构建继承类:TOutPortThread
///////////////// InheritUnit.pas
unit InheritUnit;

interface

uses
Classes, DB, ADODB, forms,SysUtils,ComCtrls, Windows, ADOThread;

type
TOutPortThread = class(TOpenSQLThread)
private
FADOQuery:TAdoQuery;
FileName, FStrSQL: string;
list: TStrings;
procedure UpdateProcess;
protected
procedure Execute; override;
public

constructor Create(CreateSuspended: Boolean; aFileName,{文件名} ConnString,StrSQL:{表名} string;hMutex:THandle);
destructor Destroy; override;
end;

Const
ZChar=' ';

implementation

uses
DataImportUnit;

constructor TOutPortThread.Create(CreateSuspended: Boolean; aFileName,
ConnString,StrSQL: string; hMutex:THandle);
begin
inherited Create(CreateSuspended,ConnString,StrSQL,hMutex);
list := TStringList.Create;
FileName:=aFileName;
end;

procedure TOutPortThread.Execute;
var
filePath,stemp,lines,tmpstr:string;
j:integer;
begin
inherited; //这里好象并没有对FADOQuery进行处理

filePath:=ExtractFilePath(Application.ExeName) + FileName;
list.Add(FADOQuery.SQL.Text); //这个地方出现错误,FADOQuery好象并没有创建。
list.Add('***文件类型:' + FileName + '***');
stemp := '';
for j := 0 to FADOQuery.fields.count - 1 do
begin
if Uppercase(FADOQuery.Fields[j].FullName) <> 'ID' then
if (FADOQuery.Fields[j].DataType <> ftGraphic)
and (FADOQuery.Fields[j].DataType <> ftBlob) then ////跳过Image型
stemp := stemp + FADOQuery.fields[j].FullName + ZChar;
end;
stemp := copy(stemp, 1, length(stemp) - 1);
list.Add(stemp);
FADOQuery.First;
while not eof do
begin
Synchronize(UpdateProcess);
sleep(100);
Lines := '';
for j := 0 to FADOQuery.fields.count - 1 do
begin
if Uppercase(FADOQuery.Fields[j].FullName) <> 'ID' then
if (FADOQuery.Fields[j].DataType <> ftGraphic) and (FADOQuery.Fields[j].DataType <>
ftBlob) then ////跳过Image型
begin
tmpStr := trim(FADOQuery.Fields[j].AsString);
tmpStr := StringReplace(tmpStr, #13 + #10, ' ', [rfReplaceAll]);
Lines := Lines + #39 + tmpStr + #39 + ZChar;
end;
end;
Lines := copy(Lines, 1, length(Lines) - 1);
list.Add(Lines);
FADOQuery.Next;
end;

list.SaveToFile(filePath);
end;

procedure TOutPortThread.UpdateProcess;
var
ProgressBar:TProgressBar;
begin
if FileName='outputfile.txt' then ProgressBar:= FormDataImport.ProgressBarOut
else if FileName='outputfile1.txt' then ProgressBar:= FormDataImport.ProgressBar1
else if FileName='outputfile2.txt' then ProgressBar:= FormDataImport.ProgressBar2
else if FileName='outputfile3.txt' then ProgressBar:= FormDataImport.ProgressBar3;


if ProgressBar.Position >= 100 then
ProgressBar.Position := 0
else
ProgressBar.Position :=
ProgressBar.Position
+ ProgressBar.Step;
application.ProcessMessages; //切换,给其他线程运行时间
end;

destructor TOutPortThread.Destroy;
begin
list.Free;
inherited;
end;

end.


////////////// 调用DataImportUnit.pas
unit DataImportUnit;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, DB, ADODB,Activex;

type
TFormDataImport = class(TForm)
ProgressBarOut: TProgressBar;
Button1: TButton;
ADOConnection1: TADOConnection;
ProgressBar1: TProgressBar;
ProgressBar2: TProgressBar;
ProgressBar3: TProgressBar;
ADOConnection2: TADOConnection;
ADOQuery1: TADOQuery;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
FormDataImport: TFormDataImport;
hMutex: THandle = 0;

implementation

uses
UnitConst,InheritUnit;

{$R *.dfm}

procedure TFormDataImport.Button1Click(Sender: TObject);
begin

hMutex := CreateMutex(nil, False, nil);

TOutPortThread.Create(false,'outputfile.txt',StrConn,'select * from employee',hMutex);
TOutPortThread.Create(false,'outputfile1.txt',StrConn,'select * from authors',hMutex);
TOutPortThread.Create(false,'outputfile2.txt',StrConn,'select * from jobs',hMutex);
TOutPortThread.Create(false,'outputfile3.txt',StrConn,'select * from sales',hMutex);

end;


initialization
CoInitializeEx(nil,COINIT_MULTITHREADED);
finalization
CoUninitialize;

end.

而在procedure TOutPortThread.Execute;中
inherited; //这里好象并没有对FADOQuery进行处理
list.Add(FADOQuery.SQL.Text); //这个地方出现错误,FADOQuery好象并没有创建。



 
我是想先构建TExecSQLThread和TOpenSQLThread类。

在这两个基类中,进行线程执行SQL和打开查询。在创建类时,输入参数ADO的连接字符串与SQL字符串,互斥句柄。(ADOThread.pas)

然后,再建类继承自这基类,实现功能。与主线程同步。
(OutPortUnit.pas,这个单元中实现将数据库数据内容通过TStringList输出到文本中。)

但在procedure TOutPortThread.Execute;中
inherited; //这里好象并没有对FADOQuery进行处理
list.Add(FADOQuery.SQL.Text); //这个地方出现错误,FADOQuery好象并没有创建。

源程序如下:
/////////// 基类 ADOThread.pas
unit ADOThread;

interface

uses
Classes, DB, ADODB, forms,SysUtils,ComCtrls, Windows;

type
TExecSQLThread = class(TThread)
private
FMutex:THandle;
FExecTime:Integer;
FADOConnection: TADOConnection;
FADOQuery: TAdoQuery;
procedure ADOTimeOut;
procedure ADOExecSQL;
protected
procedure Execute; override;
public
constructor Create(CreateSuspended: Boolean; ConnString,StrSQL:string;hMutex:THandle); overload;
destructor Destroy; override;
end;

type
TOpenSQLThread = class(TThread)
private
FMutex:THandle;
FExecTime:Integer;
FADOConnection: TADOConnection;
FADOQuery: TAdoQuery;
procedure ADOTimeOut;
procedure ADOOpenSQL;
protected
procedure Execute; override;
public

constructor Create(CreateSuspended: Boolean; ConnString,StrSQL:string;hMutex:THandle); overload;
destructor Destroy; override;
end;

implementation

constructor TExecSQLThread.Create(CreateSuspended: Boolean; ConnString,
StrSQL:string;hMutex:THandle);
begin
inherited Create(CreateSuspended);
FADOConnection:= TAdoConnection.Create(Application);
FADOConnection.ConnectionString:=ConnString;
FADOConnection.LoginPrompt:=false;
FADOQuery := TAdoQuery.Create(Application);
FADOQuery.SQL.Add(StrSQL);
FExecTime:=0;
FMutex:=hMutex;
self.FreeOnTerminate:=true; //必须加上,否则不能释放内存
end;

destructor TExecSQLThread.Destroy;
begin
FADOQuery.Close;
FADOQuery.Free;
FADOConnection.Close;
FADOConnection.free;
inherited;
end;

procedure TExecSQLThread.Execute;
begin
if WaitForSingleObject(FMutex, INFINITE) = WAIT_OBJECT_0 then
begin
FADOConnection.Open;
ADOExecSQL;
end;
ReleaseMutex(FMutex);

{ Place thread code here }
end;

procedure TExecSQLThread.ADOExecSQL;
begin
try
FExecTime:=FExecTime+1;
if FExecTime<=3 then FADOQuery.ExecSQL
else Synchronize(ADOTimeOut);
except
ADOExecSQL;
end;
end;

procedure TExecSQLThread.ADOTimeOut;
begin

end;

constructor TOpenSQLThread.Create(CreateSuspended: Boolean; ConnString,
StrSQL:string;hMutex:THandle);
begin
inherited Create(CreateSuspended);
FADOConnection:= TAdoConnection.Create(Application);
FADOConnection.ConnectionString:=ConnString;
FADOConnection.LoginPrompt:=false;
FADOQuery := TAdoQuery.Create(Application);
FADOQuery.Connection:=FADOConnection;
FADOQuery.SQL.Add(StrSQL);
FExecTime:=0;
FMutex:=hMutex;
self.FreeOnTerminate:=true; //必须加上,否则不能释放内存
end;

destructor TOpenSQLThread.Destroy;
begin
FADOQuery.Close;
FADOQuery.Free;
FADOConnection.Close;
FADOConnection.free;
inherited;
end;

procedure TOpenSQLThread.ADOOpenSQL;
begin
try
FExecTime:=FExecTime+1;
if FExecTime<=3 then FADOQuery.Open
else Synchronize(ADOTimeOut);
except
ADOOpenSQL;
end;
end;

procedure TOpenSQLThread.ADOTimeOut;
begin

end;


procedure TOpenSQLThread.Execute;
var
filePath,stemp,lines,tmpstr:string;
j:integer;
begin
if WaitForSingleObject(FMutex, INFINITE) = WAIT_OBJECT_0 then
begin
FADOConnection.Open;
ADOOpenSQL;
end;
ReleaseMutex(FMutex);

{ Place thread code here }
end;


end.



下面构建继承类:TOutPortThread
///////////////// InheritUnit.pas
unit InheritUnit;

interface

uses
Classes, DB, ADODB, forms,SysUtils,ComCtrls, Windows, ADOThread;

type
TOutPortThread = class(TOpenSQLThread)
private
FADOQuery:TAdoQuery;
FileName, FStrSQL: string;
list: TStrings;
procedure UpdateProcess;
protected
procedure Execute; override;
public

constructor Create(CreateSuspended: Boolean; aFileName,{文件名} ConnString,StrSQL:{表名} string;hMutex:THandle);
destructor Destroy; override;
end;

Const
ZChar=' ';

implementation

uses
DataImportUnit;

constructor TOutPortThread.Create(CreateSuspended: Boolean; aFileName,
ConnString,StrSQL: string; hMutex:THandle);
begin
inherited Create(CreateSuspended,ConnString,StrSQL,hMutex);
list := TStringList.Create;
FileName:=aFileName;
end;

procedure TOutPortThread.Execute;
var
filePath,stemp,lines,tmpstr:string;
j:integer;
begin
inherited; //这里好象并没有对FADOQuery进行处理

filePath:=ExtractFilePath(Application.ExeName) + FileName;
list.Add(FADOQuery.SQL.Text); //这个地方出现错误,FADOQuery好象并没有创建。
list.Add('***文件类型:' + FileName + '***');
stemp := '';
for j := 0 to FADOQuery.fields.count - 1 do
begin
if Uppercase(FADOQuery.Fields[j].FullName) <> 'ID' then
if (FADOQuery.Fields[j].DataType <> ftGraphic)
and (FADOQuery.Fields[j].DataType <> ftBlob) then ////跳过Image型
stemp := stemp + FADOQuery.fields[j].FullName + ZChar;
end;
stemp := copy(stemp, 1, length(stemp) - 1);
list.Add(stemp);
FADOQuery.First;
while not eof do
begin
Synchronize(UpdateProcess);
sleep(100);
Lines := '';
for j := 0 to FADOQuery.fields.count - 1 do
begin
if Uppercase(FADOQuery.Fields[j].FullName) <> 'ID' then
if (FADOQuery.Fields[j].DataType <> ftGraphic) and (FADOQuery.Fields[j].DataType <>
ftBlob) then ////跳过Image型
begin
tmpStr := trim(FADOQuery.Fields[j].AsString);
tmpStr := StringReplace(tmpStr, #13 + #10, ' ', [rfReplaceAll]);
Lines := Lines + #39 + tmpStr + #39 + ZChar;
end;
end;
Lines := copy(Lines, 1, length(Lines) - 1);
list.Add(Lines);
FADOQuery.Next;
end;

list.SaveToFile(filePath);
end;

procedure TOutPortThread.UpdateProcess;
var
ProgressBar:TProgressBar;
begin
if FileName='outputfile.txt' then ProgressBar:= FormDataImport.ProgressBarOut
else if FileName='outputfile1.txt' then ProgressBar:= FormDataImport.ProgressBar1
else if FileName='outputfile2.txt' then ProgressBar:= FormDataImport.ProgressBar2
else if FileName='outputfile3.txt' then ProgressBar:= FormDataImport.ProgressBar3;


if ProgressBar.Position >= 100 then
ProgressBar.Position := 0
else
ProgressBar.Position :=
ProgressBar.Position
+ ProgressBar.Step;
application.ProcessMessages; //切换,给其他线程运行时间
end;

destructor TOutPortThread.Destroy;
begin
list.Free;
inherited;
end;

end.


////////////// 调用DataImportUnit.pas
unit DataImportUnit;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, DB, ADODB,Activex;

type
TFormDataImport = class(TForm)
ProgressBarOut: TProgressBar;
Button1: TButton;
ADOConnection1: TADOConnection;
ProgressBar1: TProgressBar;
ProgressBar2: TProgressBar;
ProgressBar3: TProgressBar;
ADOConnection2: TADOConnection;
ADOQuery1: TADOQuery;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
FormDataImport: TFormDataImport;
hMutex: THandle = 0;

implementation

uses
UnitConst,InheritUnit;

{$R *.dfm}

procedure TFormDataImport.Button1Click(Sender: TObject);
begin

hMutex := CreateMutex(nil, False, nil);

TOutPortThread.Create(false,'outputfile.txt',StrConn,'select * from employee',hMutex);
TOutPortThread.Create(false,'outputfile1.txt',StrConn,'select * from authors',hMutex);
TOutPortThread.Create(false,'outputfile2.txt',StrConn,'select * from jobs',hMutex);
TOutPortThread.Create(false,'outputfile3.txt',StrConn,'select * from sales',hMutex);

end;


initialization
CoInitializeEx(nil,COINIT_MULTITHREADED);
finalization
CoUninitialize;

end.

而在procedure TOutPortThread.Execute;中
inherited; //这里好象并没有对FADOQuery进行处理
list.Add(FADOQuery.SQL.Text); //这个地方出现错误,FADOQuery好象并没有创建。



 
好复杂呢,看不是很明白!
 
问题我解决了。

这个里面一定要注意继承中属性的关系。
在ADOThread.pas中
type
TOpenSQLThread = class(TThread)
private
.....
FADOQuery: TAdoQuery;
.....
protected
.....
property ADOQuery: TAdoQuery read FADOQuery; //这个非常重要。
.....
end;

然后在OutPortUnit.pas中,直接引用 ADOQuery 就可以了。

这个ADOThread.pas可以直接引用。用于构建ADOThread的子类,然后应用到实际中去。
 
没仔细看,随便瞎说一下:
试试Pooling...
 
Pooling...
是什么东西?
 
Pooling...
是什么东西?
 
list.Add(FADOQuery.SQL.Text); //这个地方出现错误,FADOQuery好象并没有创建
FADOQuery没有创建可能是在FADOQuery := TAdoQuery.Create(Application);
把Application改为nil,因为是多线程
不知TStringList是否线程安全可用CheckSynchronize检查一下如果不行的话就把
TStringList 改为TThreadList
 
不知道楼上说的是什么?
 
顶部