子线程中的变量地址可能被破坏?(100分)

C

cgs1980

Unregistered / Unconfirmed
GUEST, unregistred user!
我有3个线程,线程 A 启动线程B, 并且线程A传递给线程B一个参数 ID(该ID赋值给线程B的 FID变量), 然后线程B执行时又会启动一个线程C, 线程B等待线程C执行完毕后,会对一个 ListView 进行更新,但此时发现线程B的 private 变量 FID 的值不等于线程A传递过来的值,我已经初步分析出原因,见下述,但有什么方法可以解决呢?示例代码如下所示:
AThread = class(TThread)
private
FListView1: TListView;
protected
procedure Execute;
override;
public
constructor Create();
end;

BThread = class(TThread)
private
FListView: TListView;
FID: Integer;
FTotalNumber: Integer;
procedure ThreadDone(Sender: TObject);
procedure UpdateInfo();
protected
procedure Execute;
override;
public
constructor Create(ListView: TListView;
ID: Integer);

end;

CThread = class(Thread)
protected
FStr: string;
FTotal: Integer ;

proceduredo
SomeThings();
protected
procedure Execute;
override;
public
property Total: Integerl read FTotal write FTotal;
constructor Create(Str: string);
end;

procedure AThread.Execute;
var
i, count: Integer;
begin
for i:=0 to 1do
begin
BThread.Create(FListView1, i);
end;
end;

constructor ThreadB.Create(ListView2: TListView;
ID: Integer);
begin
FListView := ListView2;
FID := ID;
FreeOnTerminate := True;
inherited Create(False);
end;

procedure BThread.Execute;
var
i, count: Integer;
str: String;
begin
Str := GetSomeThings();
with CThread.Create(Str)do
begin
OnTerminate := ThreadDone ;
end;
end;

procedure BThread.ThreadDone(Sender: TObject);
begin
if (Sender is CThread) then
begin
FTotalNumber := CThread(Sender).Total;
Synchronize( UpdateInfo );
end;
end;

procedure BThread.UpdateInfo();
var
index: Integer;
begin

[red]// 当线程CThread执行完毕后,BThread会执行这个UpdateInfo,但我多次跟踪测试,此时的 FID的取值与AThread传递的值不同,为什么呢?[/red]
FListView2.Items.Item[FID].Caption := IntToStr( FTotalNumber );
end;

procedure CThread.Execute;
begin
Total :=do
SomeOtherThings();
end;

当线程CThread执行完毕后,BThread会执行这个UpdateInfo函数,但我多次跟踪测试,执行此函数时, FID的取值与AThread传递的值不同,例如:线程A传递给线程B的 ID := 0,但当执行UpdateInfo函数时,FID 值发生了随机性的变化,多次测试,FID的值为 1868627968、58297等, 经过分析, 可能是由于我在线程C 的do
SomeOtherThings() 函数中加载了一个hash表(该表为全局变量),该表有几万条记录,当第一次执行 线程C时,会加载这个hash表,再次执行时,不会加载这个hash表(已经加载) , 那么可能存在一个原因是:当第一次加载hash表时,程序要分配一定的空间,此时将线程B的一些变量空间覆盖了。当hash表已经加载,再次启动线程B、线程C时,当执行 UpdateInfo函数时,FID的取值与AThread传递的值是相同的了,如果是因为hash表导致线程B的变量被覆盖,那么有什么方法可以避免这种情况呢?谢谢大家的指点。
 
H

hfghfghfg

Unregistered / Unconfirmed
GUEST, unregistred user!
你是不是 多个线程 都启动了
你调试时 看错 把2个线程 看在一起了
我估计 是 你多个 线程 同时 工作时 的问题
还有 你这样
FListView2.Items.Item[FID]
有点 怪怪的
如果 FListView2.Items 有插入 或删除 你的FID 不是错位了
 
H

hfghfghfg

Unregistered / Unconfirmed
GUEST, unregistred user!
估计 是
TThread 。 Create(ListView: TListView;
ID: Integer);
传了 ID
。。。。
这时 FListView2.Items 有插入 或删除
。。。。
Thread.Execute;
你的UpdateInfo 还用原来的ID
FListView2.Items.Item[FID] 就错位了
 
C

cgs1980

Unregistered / Unconfirmed
GUEST, unregistred user!
我调试时,线程A启动一个线程B,然后线程B执行时会启动一个线程C,我是这样逐步调试的, FListView2.Items 不会进行删除操作, 在线程B中我只想对 FListView2.Items.Item[FID] 的Caption信息进行更新。
 
H

hfghfghfg

Unregistered / Unconfirmed
GUEST, unregistred user!
你查查 是不是 几个线程都启动了
你看花眼了
 
H

hfghfghfg

Unregistered / Unconfirmed
GUEST, unregistred user!
FListView2 你绑定了 排序没有
是不是 你 Caption 更新 自动排序了
 
C

cgs1980

Unregistered / Unconfirmed
GUEST, unregistred user!
在线程C中加载了一个hash表,该表有几万条记录,可能是因为线程C中加载的这个hash表空间覆盖了线程B的变量空间,导致线程B的变量值发生变化,但有什么方法可以避免这种情况呢?对线程B的变量进行保护。
 
H

hfghfghfg

Unregistered / Unconfirmed
GUEST, unregistred user!
覆盖了线程C的变量空间
就是 你内存越界了
那是 的写法错误了
 
H

hfghfghfg

Unregistered / Unconfirmed
GUEST, unregistred user!
如果 你内存 都越界
那 啥事 都有可能 出现
总之 千万 不要越界
几万条记录 是小case啊
你肯定那里的 下标越界了
或者内存分配有问题
 
C

cgs1980

Unregistered / Unconfirmed
GUEST, unregistred user!
我将线程B中UpdateInfo()函数的更新操作移到线程C中就不会出现问题了,还发现一点,如果我将线程B的 FID变量移出来作为一个全局变量也不会出现问题了。谢谢 hfghfghfg !
 
顶部