谁能举个多线程的例子!(50分)

  • 主题发起人 主题发起人 dana
  • 开始时间 开始时间
D

dana

Unregistered / Unconfirmed
GUEST, unregistred user!
比如有一数据库,从头到尾循环,做某一件事,这样如何动态创建线程。
while not eofdo

begin

end;
谁能给点思路或例程,我不明白该如何创建。
我只想知道多线程的原理,请大家帮忙!
 
Delphi中有现成的例子:
Program Files/Borland/Delphi5/Demos/Threads
 
例子看不太明白。
以下一个例程,可是这样对数据库又是如何分开操作。我要让每个线程执行不同的记录。
unit Unit2;
interface
uses
Classes,Db, DBTables,StdCtrls, SysUtils;
type
j = class(TThread)
private
query:Tquery;
protected
procedure Execute;
override;
end;

implementation
procedure j.Execute;
begin
freeonterminate:=true;
query:=Tquery.Create(nil);
query.DatabaseName:='delphi';
with querydo
begin
close;
sql.Clear ;
sql.add('select * from abc');
.....
open;
end;
if terminated then
exit;
end;

end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Db, DBTables;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
th:array[1..10] of TThread;
implementation
uses Unit2;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i:=1 to 10do
th:=j.Create(false);
end;
end.
 
比如如何让
第一个线程执行第1-10条记录,
第二个线程执行第11-20条记录
....
 
我明白你的意思了,如果你这样做是为了加快速度的话,我觉得这样并不能加快速度。
不过也许你有别的用处,以下是我的一些建议:
首先这张表应有一个ID字段,以便使用SQL语句能够找到相应的记录,
第1个线程执行语句 select * from abc where id between 1 and 10
的2个线程执行语句 select * from abc where id between 11 and 20
...
然后线程应知道自己是第几个线程,即线程编号,你可以重载TThread.Create过程,
为其增加一个参数,在主程序创建线程时对不同的线程传入不同的编号,
在线程内部根据编号执行不同的查询语句。
 
那么在这个线程中我该如何带一线程的参数。
procedure j.Execute;
begin
freeonterminate:=true;
query:=Tquery.Create(nil);
query.DatabaseName:='delphi';
with querydo
begin
close;
sql.Clear ;
sql.add('select * from abc');
.....
open;
end;
if terminated then
exit;
end;
 
重新定义TThread.Create过程,并在线程中增加一个成员变量:
type
j = class(TThread)
private
query:Tquery;
FNo: Integer;
//增加一个成员变量用以记录传入参数
protected
procedure Execute;
override;
public
constructor Create(No: Integer);
//重新定义Create,增加一个参数No
end;

constructor j.Create(No: Integer);
begin
FNo := No;
//把传入参数赋值给成员变量记录下来
FreeOnTerminate := True;
inherited Create(False);
end;

procedure j.Execute;
begin
freeonterminate:=true;
query:=Tquery.Create(nil);
query.DatabaseName:='delphi';
with querydo
begin
close;
sql.Clear ;
//此处利用FNo查询表中的不同记录
sql.add('select * from abc where id between '
+ IntToStr((FNo - 1) * 10 + 1) + ' and ' + IntToStr(FNo * 10) );
.....
open;
end;
if terminated then
exit;
end;

//最后在主程序中把编号传进去
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
begin
for i:=1 to 10do
th:=j.Create(i);
end;
 
还有一问题不明白,因为我需要用到同步执行,那参数又该如何传送?
procedure j.doquery(nthread:integer);
begin
query:=Tquery.Create(nil);
query.DatabaseName:='DBDEMOS';
with querydo
begin
close;
sql.Clear ;
sql.add('select * from country');
if nthread=1 then
.............
open;
end;
end;

procedure ss.Execute;
begin
threadlist.add(self);
freeonterminate:=true;
synchronize(doquery);
if terminated then
exit;
end;

 
把nthread放到线程类定义中作为成员变量,这样就不必传递参数,可以被doquery直接使用。
就象我上面写的例子中那样。
另外提醒你一件事:
在不同的线程中访问数据库应使用不同的Session,这是Delphi的要求。
缺省情况下,所有的TDatabase均使用同一个缺省的Session,由系统自动创建。
现在你应该为每一个线程自行创建TSession,然后将Database的SessionName置成自己的SessionName。
 
可是我不知道这该如何带能参数。synchronize(doquery(...));
我写的doquery过程这样应该没错吧!(我对线程的概念还非常模糊)
动态创建session,应如何创建。
 
看来你还没有明白我的意思,doquery过程不需要参数!!!
在doquery过程内部读成员变量。
仔细看看上面我写的例子中j.Execute中sql.add那段话。
 
多谢!
动态创建session是否和query一样,
seee:=tsession.create(nil)
query:=Tquery.Create(nil);
query.DatabaseName:='DBDEMOS';
query.sessin:=sess;
对吗?
 
还有一疑问
nthread:这个作为成员变量在多线程中不会乱掉吗?
 
应该是:
ssn := TSession.Create(nil);
db := TDatabase.Create(nil);
qry := TQuery.Create(nil);
ssn.SessionName := 'MySession1';
db.DatabaseName := 'DBDEMOS';
db.SessionName := 'MySession1';
qry.SessionName := 'MySession1';
qry.DatabaseName := DBDEMOS';
 
不会乱。每个线程有各自的一套成员变量,就像两个按钮都是TButton,但是各自的
Caption属性不会乱一样。
 
非常感谢!
再问一个小问题希望同样能得到您的帮助。
何为临界区,有何用处。
threadlist:=tthreadlist.create;
m_criticalsection:=tcriticalsection.create;
 
抱歉,临界区我没用过,不过看help的意思是个加锁机制,让其它线程暂时停止一切操作,
等当前线程做完某件事之后再继续。
 
真不好意思再麻烦你一下行吗?我使用的是ado,
在ado中没的定义session那么我这个又该如何创建。
ssn := TSession.Create(nil);
db := TDatabase.Create(nil);
qry := TQuery.Create(nil);
ssn.SessionName := 'MySession1';
db.DatabaseName := 'DBDEMOS';
db.SessionName := 'MySession1';
qry.SessionName := 'MySession1';
qry.DatabaseName := DBDEMOS';
 
很抱歉,我用的是BDE,不是ADO。
既然ADO中不能自己创建Session,那么就应该没有这个限制,你还是用原先的写法吧。
 
是不是在线程中所使用到的变量,一定要定义到成员变量中去,
我要是只定义为全局变量,不行吗?

 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
后退
顶部