关于多个线程访问TStringList全局变量的同步问题???

mylyqc 2013-12-13 05:23:37

关于多个线程访问TStringList的同步问题


关于多个线程访问TStringList的同步问题:
我的想法是:复制TStringList到另一个TStringList变量,来实现在多个线程里同步访问TStringList变量。

如下:
自定义类:
TNodeData = Class
ID, PID, NodeText : string;
end;

全局变量:
m_List: TStringList;
m_List:= TStringList.Create;

m_cs: TCriticalSection;
m_cs:= TCriticalSection.Create;

初始化m_List成员值:
procedure TMainForm.FormCreate(Sender: TObject);
var
NodeData: TNodeData;
qry: TASQLite3Query;
begin
...
while not qry.Eof do
begin
NodeData:= TNodeData.Create;
NodeData.ID := qry.FieldByName('ID').AsString;
pChildNodeData.PID := qry.FieldByName('PID').AsString;
pChildNodeData.NodeText := qry.FieldByName('NodeText').AsString;
m_List.AddObject(NodeData.NodeText,NodeData);
qry.Next;
end;
qry.Close;
qry.Free;
...
end;


因在其它多个线程和主界面线程都有访问m_List,所以想到要做同步:我的想法就是复制一个m_List的副本出来供其它各线程来调用。

复制全局变量m_List的自定义函数:
function CopyStringListContent(ls:TStringList):boolean;
begin
try
try
m_cs.Enter;
ls.Assign(m_List);
result:= true;
finally
m_cs.Leave;
end;
except
result:= false;
end;
end;

线程1里的m_List访问:在副本里访问m_List的值:
var
list: TStringList;
begin
...
list := TStringList.Create;
if not CopyStringListContent(list) then //复制一个与m_List相同值的TStringList新的变量list。
exit;
for i:= 0 to list.Count-1 do
begin
...
list.Objects[i].Free; //操作完成后释放局部变量list里的对象
end;
list.Free;
...
end;


运行以上代码后,这时候假如在其它地方再有访问m_List里的对象就会出错!因为m_List里的对象被释放了。
如下:
for i:= 0 to m_List.Count-1 do
begin
strNodeID := TNodeData(m_List.Objects[i]).ID; //这里就报错了!
strNodeText:= TNodeData(m_List.Objects[i]).NodeText;
m_List.Objects[i].Free;
end;



问题1:执行CopyStringListContent函数里ls.Assign(m_List);后m_List和list变量指向的还是同一个内存块。
所以我改为下面的代码来复制m_List的值,
请问还有更方便的方法吗???
function CopyStringListContent(ls:TStringList):boolean;
var
i:integer;
node:TNodeData;
begin
try
try
m_cs.Enter;
for i:= 0 to m_List.Count-1 do
begin
node := TNodeData.Create;
node.ID := TNodeData(m_List.Objects[i]).ID;
node.PID:= TNodeData(m_List.Objects[i]).PID;
node.NodeText:= TNodeData(m_List.Objects[i]).NodeText;
ls.AddObject(node.NodeText,node);
end;
result:= true;
finally
m_cs.Leave;
end;
except
result:= false;
end;
end;


问题2:请教各位说在多个线程里实现同步同一个全局变量的方法。
...全文
292 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
sololie 2013-12-14
  • 打赏
  • 举报
回复
LZ应该再看看线程同步的相关原理 如果不想看,如果你的线程中对那个变量只是读而不写,也可以不做同步,但有可能会影响到改变量的更新。 另外to ls,threadvar至少在 d5开始就有了,不一定要d2010,D5之前没用过不知道。不过threadvar的作用跟LZ的需求没什么关系,threadvar声明的变量的作用是为不同的线程中存储不同的值。
孤独de猫 2013-12-14
  • 打赏
  • 举报
回复
在D2010的版本中,可以使用ThreadVar 来申明一个线程变量。或者使用互斥区来访问。
mylyqc 2013-12-13
  • 打赏
  • 举报
回复
但是我在多个线程的不同的函数里都有使用到m_List,而且是一直死循环来读取m_List的。 代码如下: while not terminated do begin for i:= 0 to m_List.Count-1 do begin 取值TNodeData(m_List.Objects[i]).ID 用来做一些工作。 end; end; 当其它线程还在循环调用m_List时,如果这时候m_List被在主界面操作删除了一个成员,那么上面的代码不就有可能出错了? 像这样的死循环,我又不能加 m_cs.Enter 和 m_cs.Leave 来保护,因为加了会使这个循环会一直占用m_List。
sololie 2013-12-13
  • 打赏
  • 举报
回复
用互斥体或临界区等,搜一下吧,满天都是
mylyqc 2013-12-13
  • 打赏
  • 举报
回复
问题2:请教各位大侠,在多个线程里实现同步访问同一个全局变量的方法???
sololie 2013-12-13
  • 打赏
  • 举报
回复
用 TThreadList

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧