关于线程中变量的使用。(200分)

  • 主题发起人 主题发起人 jason_fox
  • 开始时间 开始时间
J

jason_fox

Unregistered / Unconfirmed
GUEST, unregistred user!
我声明了一个recorder类型TTaskrec, 在Thread create时传递一个TTaskrec变量给FTaskrec
但是在Thread 的Execute调用过程RepairThreadExecute会丢失?!
原码如下。
{在一公共文件中。声明的TTaskrec类型}
type
TTaskRec = record
rId:integer;
rStatus:integer;
rDatabaseName:string[100];
rDatabaseType:integer;
rServerName:string[50];
rUserName:string[50];
rPassword:string[50];
rBackupPath:string[200];
rBackupFileName:string[50];
risCompress:boolean;
risMultiSaved:boolean;
rMethodType:integer;
end;

unit UntQueryThread;
interface
uses
Classes,DB,DBTables,untglobal,DataModMain;
type
TTaskThread = class(TThread)
private
FTaskrec : TTaskRec;
//!
Fstrings1: Tstrings;
Fstrings2: Tstrings;
protected
procedure Execute;
override;
Procedure RepairThreadExecute;
proceduredo
Execute;
//virtual;
abstract;
public
constructor Create(ATaskrec:TTaskrec);
end;
implementation
{ TTaskThread }
constructor TTaskThread.Create(ATaskrec:TTaskrec);
begin
inc(gTaskRunning);
FTaskrec := ATaskrec;
//传递变量,此时变量正常。
inherited Create(False);
//
FreeOnTerminate:=true;
end;

procedure TTaskThread.Execute;
begin
{ Place thread code here }
RepairThreadExecute;
do
Execute;
// record the connect message to table (tasklog)
end;

procedure TTaskThread.doExecute;
begin
{ Place thread code here }
case TDatabaseType(FTaskrec.rDatabaseType) of
dbSybase:
with MainDataModdo
begin
{set the property of database}
DatabaseThd1.DriverName := 'SYBASE';
DatabaseThd1.Params.Clear;
DatabaseThd1.Params.Assign(Fstrings1);
QueryThd1.SQL.clear;
QueryThd1.SQL.Assign(Fstrings2);
{ execute the query.}
//try
DatabaseThd1.Connected := True;
// record the connect message to table (tasklog)
QueryThd1.ExecSQL;
// record the connect message to table (tasklog)
DatabaseThd1.Connected := False;
{set the status of the task. }
updateTaskStatus(FTaskrec.rId,isWaiting);
//except
//end;
end;
// record the connect message to table (tasklog)
dbAnywhere:;
end;
end;
procedure TTaskThread.RepairThreadExecute();
var
lstr1:string;
begin
{***!FTaskrec的值丢失,变为乱七八糟。 这一步有时是好的,有时会丢失。}
case TDatabaseType(FTaskrec.rDatabaseType) of
{***!FTaskrec的值丢失,变为乱七八糟。 到这变量肯定丢了!}
dbSybase:
begin
Fstrings1.Clear;
lstr1:='SERVER NAME='+FTaskrec.rServerName;
Fstrings1.Add(lstr1);
lstr1:='USER NAME='+FTaskrec.rUserName;
Fstrings1.Add(lstr1);
lstr1:='PASSWORD='+FTaskrec.rPassword;
Fstrings1.Add(lstr1);
{lstr1:='DATABASE NAME='+FTaskrec.rDatabaseName;
Fstrings1.Add(lstr1);}
Fstrings2.Clear;
lstr1:='dump database '+FTaskrec.rDatabaseName+' to '''+
FTaskrec.rBackupPath + FTaskrec.rBackupFileName +'''';
Fstrings2.Add(lstr1);
end;
dbAnywhere:
begin

end;
end;
end;
end.
 
???!!!!
 
加个new(FTaskrec)试试[8D]
 
如果你要想传递变量值,必须加上窗体名称。
你这样试一试.
 
加上哪一个窗体的名称?
 
to singleboy :
如果是由于使用record 的原因,我在将 record 换成 普通变量后,变量仍然丢失!
是不是再现成中使用变量有特殊的要求。
 
研究,研究[:(!]
 

你的变量,是局部变量,被系统释放了,
调用在那里啊。贴一下看看!

 
不懂对不对,先说了再说:
线程的构造函数与其Execute方法是在线程启动的同时调用的,而你在构造函数中赋值
而因其同时启动,所以难免会如此,在调用时应先将线程用Resume暂时吊起来,你去看看
书上有这方面的资料,等构造函数的赋值完了,再进行方法的重载!
 
试试这样:
constructor TTaskThread.CreateIt(ATaskrec:TTaskrec);
begin
inherited Create(True);
FTaskrec := ATaskrec;
//传递变量,此时变量正常。
// Fstrings1:=TStringList.Create;
// Fstrings2:=TStringList.Create;
Suspended:=False;
self.OnTerminate:=done;
end;

procedure TTaskThread.Execute;
begin
inherited;
{ Place thread code here }
Synchronize(RepairThreadExecute);
Synchronize(doExecute);
// record the connect message to table (tasklog)
end;
还有你的Fstrings1,Fstrings2有没有创建?[?]
 
FTaskrec : TTaskRec;
//!
Fstrings1: Tstrings;
Fstrings2: Tstrings
使用时要注意create和free;
 
constructor TTaskThread.Create(ATaskrec:TTaskrec);
begin
inherited Create(False);
inc(gTaskRunning);
FTaskrec := ATaskrec;
//传递变量,此时变量正常。
//
FreeOnTerminate:=true;
end;
 
我在delphi的例子中看到同样的一个过程,传递recorder的方法,不同的是不是在tthread中。
可能诸葛兄是对的,但是不知道如何解决,是否只能以变量的方式传递?
另外,recorder是如何工作的?比如创建、传递等等?
 
to jason_fox: 经过我的监视发现我原来说的是错的,构造是先执行的,不懂是哪本书
上乱说的,不好意思,只是对象之间的传值并非是传址调用,当你在新建了其他线程后,
ATaskrec的值如果变的话,当然FTaskrec的值也会变了,你自己再看看吧
 
to jason_fox: 不知道你怎么搞的,我照你的代码运行了一下,一切正常,变量
没有丢失。下面是我简化的代码:
unit Unit3;
interface
uses
Classes, DB, DBTables;
type
TTaskRec = record
rId: integer;
rStatus: integer;
rDatabaseName: string[100];
rDatabaseType: integer;
rServerName: string[50];
rUserName: string[50];
rPassword: string[50];
rBackupPath: string[200];
rBackupFileName: string[50];
risCompress: boolean;
risMultiSaved: boolean;
rMethodType: integer;
end;

TTaskThread2 = class(TThread)
private
FTaskrec: TTaskRec;
//!
Fstrings1: Tstrings;
Fstrings2: Tstrings;
protected
procedure Execute;
override;
procedure RepairThreadExecute;
proceduredo
Execute;
//virtual;
abstract;
public
constructor Create(ATaskrec: TTaskrec);
end;
implementation
{ TTaskThread }
constructor TTaskThread2.Create(ATaskrec: TTaskrec);
begin
// inc(gTaskRunning);
FTaskrec := ATaskrec;
//传递变量,此时变量正常。
inherited Create(False);
//
FreeOnTerminate := true;
end;

procedure TTaskThread2.Execute;
begin
{ Place thread code here }
RepairThreadExecute;
do
Execute;
// record the connect message to table (tasklog)
end;

procedure TTaskThread2.doExecute;
begin
{ Place thread code here }
end;

procedure TTaskThread2.RepairThreadExecute();
var
lstr1: string;
begin
case FTaskrec.rDatabaseType of
{***!FTaskrec的值好好的,不会丢失。我都运行了十几次了}
1:
begin
Fstrings1.Clear;
lstr1 := 'SERVER NAME=' + FTaskrec.rServerName;
Fstrings1.Add(lstr1);
lstr1 := 'USER NAME=' + FTaskrec.rUserName;
Fstrings1.Add(lstr1);
lstr1 := 'PASSWORD=' + FTaskrec.rPassword;
Fstrings1.Add(lstr1);
{lstr1:='DATABASE NAME='+FTaskrec.rDatabaseName;
Fstrings1.Add(lstr1);}
Fstrings2.Clear;
lstr1 := 'dump database ' + FTaskrec.rDatabaseName + ' to ''' +
FTaskrec.rBackupPath + FTaskrec.rBackupFileName + '''';
Fstrings2.Add(lstr1);
end;
2:
begin

end;
end;
end;

{
procedure TForm1.Button1Click(Sender: TObject);
var
ATaskrec: TTaskrec;
begin
with ATaskrecdo
begin
rId:=1;
rStatus:=2;
rDatabaseName:='33333';
rDatabaseType:=4;
rServerName:='55555555';
rUserName:='66666666';
rPassword:='777777777';
rBackupPath:='8888888888888888888';
rBackupFileName:='99999999999';
risCompress:=True;
risMultiSaved:=True;
rMethodType:=10;
end;
TTaskThread2.Create(ATaskrec);
end;

}
end.

另外,我怎么觉得TTaskThread这个类名很熟似的,跟我写过的一个DEMO一样。
 
to 诸葛兄:
因为ftaskrec是线程的局部变量,所以在存放在每个
现成自己的栈中的,不会互相干扰的,应该。
 
to meady:知道了,谢谢
 
To Huzzzz:谢谢,我也一直在查找此问题的原因,希望不会和硬件有关吧!
 
后退
顶部