链表与线程 (在线等待中……) (200分)

  • 主题发起人 主题发起人 Richard3000
  • 开始时间 开始时间
R

Richard3000

Unregistered / Unconfirmed
GUEST, unregistred user!
[red]来自:Richard3000, 时间:2003-3-10 14:51:00, ID:1668867 | 编辑
我查到为什么了。
一个共用变量,一个线程,一个procedure。thread和procedure都要访问变量,procedure写
thread读。好象是thread一直占有变量,procedure得不到它,写的时候就出错了。
我想把procedure也写成thread,可是我不知道怎么控制变量的读写。用信号量,还是互斥,
还是临界区?[/red]
[blue]来自:Richard3000, 时间:2003-3-10 12:12:00, ID:1668421 | 编辑
很奇怪!
我现在改用TObjectQueue,但是在Push的时候老是出错!为什么?
Balance:=TBalance.Create;
with Balancedo
begin
WriteTime:=Now;
BalanID:=BalanID;
SerialID:=Copy(IntToStr(GetTickCount()),1,5);
Weight:=Random(300);
end;
BalanceList.BalanceQueue.Push(Balance);
//压入链表当中BalanceQueue为TObjectQueue[/blue]
目前的问题:
一台PC要用令牌的方式访问几十台电子秤。从电子秤读来的数据要保存到资料库中。因为从电子秤读数据非常快,要先存在RAM中再向Database中写。
我的想法是定义一个链表,用于保存从电子秤读来的数据。
然后用线程的Execute,把数据保存到数据库当中。
现定义数据结构如下:
unit UntBalance;
interface
uses
Windows,Classes,ADODB;
type
PBalance=^TBalanceNode;
TBalance=record
BalanID:String[2];//秤号:2位ASCII码
SerialID:String;//流水号:5位ASCII码
Weight:Double;//重量
WriteTime:Double;//最后一次访问时间
isBusy:Boolean;
end;

TBalanceNode=record //定义一个双向链表以记录从电子秤读来的数据
Balance:TBalance;
//数据
Previous:PBalance;
//前一个
Next:PBalance;
//后一个
end;

TBalanceNodeList = class(TThread)
private
ADOQuery:TADOQuery;
FHead, FTail: PBalance;
protected
procedure Execute;override;
public
constructor Create(aADOQuery:TADOQuery);
destructor Destroy;
override;
procedure Empty;
procedure Pop;
function First: TBalance;
function isEmpty:Boolean;
procedure Push(aBalance:TBalance);
end;

var
BalanceList:TBalanceNodeList;

implementation
constructor TBalanceNodeList.Create(aADOQuery:TADOQuery);
begin
FHead:=nil;
FTail:=nil;
ADOQuery:=aADOQuery;
inherited Create(false);
end;

destructor TBalanceNodeList.Destroy;
begin
Empty;
inherited;
end;

procedure TBalanceNodeList.Execute;
var
Balance:TBalance;
begin
if not Assigned(ADOQuery) then
Exit;
while Truedo
begin
if not BalanceList.isEmpty then
Balance:=BalanceList.First
else
begin
Sleep(2000);
//链表为空,休息2秒
Continue;
end;

try
with ADOQuerydo
begin
if Active then
Close;
SQL.Clear;
SQL.Add('INSERT INTO SaveData (BalanceID,Serial,WriteTime)');
SQL.Add(' VALUES (:BalanceID,:Serial,:WriteTime)');
Parameters.ParamByName('BalanceID').Value:=Balance.BalanID;
Parameters.ParamByName('Serial').Value:=Balance.SerialID;
Parameters.ParamByName('WriteTime').Value:=Balance.WriteTime;
ExecSQL;
end;

BalanceList.Pop;
//保存成功。链表的第一个无素抛出来,放弃
except
Continue;
end;
end;
end;

procedure TBalanceNodeList.Empty;
var
tempBalance:PBalance;
begin
tempBalance:=fHead;
while Assigned(tempBalance)do
begin
FHead:=FHead^.Next;
Dispose(tempBalance);
tempBalance:=fHead;
end;
end;

procedure TBalanceNodeList.Push(aBalance:TBalance);
var
tempBalance:PBalance;
begin
tempBalance:=FTail;
if Assigned(FTail) then
//链表不空
begin
New(FTail^.Next);
tempBalance^.Next:=FTail;
FTail^.Previous:=tempBalance;
end else
begin
New(FHead);
New(FTail);
FHead^.Next:=FTail;
FTail^.Previous:=FHead;
end;
FTail^.Balance:=aBalance;
end;

function TBalanceNodeList.isEmpty;
begin
Result:=(FHead=nil) or (FHead^.Next=nil) or (FHead=FTail);
end;

procedure TBalanceNodeList.Pop;
var
pTemp:PBalance;
begin
if isEmpty then
Exit;
pTemp:=FHead^.Next;
FHead^.Next:=pTemp^.Next;
Dispose(pTemp);
end;

function TBalanceNodeList.First:TBalance;
begin
Result:=FHead^.Balance;
end;

end.

但是在POP时经常出错。
不知道为什么?
请各位仁兄帮我!

 
我的想法是定义一个链表,用于保存从电子秤读来的数据。
然后用线程的Execute,把数据保存到数据库当中。
 
会出错吗?出什么错?这样可以让人容易判断一些。
一般想来,有可能是Push和Pop之间造成冲突造成的,
我猜想,Push是由外部其他线程调用的吧?
 
每次总是访问同一个数据。
 
你链表的双向的,你忘了另外的Previous指针了
procedure TBalanceNodeList.Pop;
var
pTemp:PBalance;
begin
if isEmpty then
Exit;
pTemp:=FHead^.Next;

FHead^.Next:=pTemp^.Next;
pTemp^.Next^.Previous:=pTemp^.Previous
Dispose(pTemp);
end;
 
我以前对工控参数的读取分析处理是这样做的,用定时的方法从指定位置读出数据,
然后写入文件数据库dbase,然后用另一个定时程序定时读取dbase库文件分析。这样把及时处理的
一个作业让几个程序配合来做,效果还可以,也能满足及时性的处理。:)
 
Sorry! 刚才没有认真看你的代码!
.First = 什么? Head.Balance
.Pop 做了什么? Head 不变,释放的是 Head.Next!
所以就错了。
 
多谢了!
现在还是不行啊。
help!!!!!!!!
 
现在又怎么了呢?把错误情况说出来吧,不要再玩猜谜游戏了。@_@
 
多线程之间需要同步,否则会出现不可预料的冲突或错误
相关问题,请参照
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1654444
和你的问题是有关系的
关键是线程之间的互斥与同步
关于链表,可以用TQueue Delphi提供的类
或者TList也可以
前者定义在单元Contnrs中
 
现在的错误是无效的指针操作!
[red]Invalid pointer operation[/red]
 
可以预先分配足够的内存,自己可以用链表保存空闲的内存块的索引,来自己分配内存
比起频繁的分配内存速度更快,不会产生泄漏
 
>>LiChaoHui
如何做?
请各位继续关注!
 
多线程之间需要同步,否则会出现不可预料的冲突或错误
相关问题,请参照
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1654444
和你的问题是有关系的
关键是线程之间的互斥与同步
关于链表,可以用TQueue Delphi提供的类
或者TList也可以
前者定义在单元Contnrs中
 
多谢LiChaoHui!
我试试。
请各位继续关注!
 
你先调一个线程的,如果一个线程不出错,那说明你是多线程访问出的问题,
需要加信号量控制。
 
to Richard3000
我关于此问题写了一个例子程序,关于线程的同步与互斥
http://www.playicq.com/dispdocnew.php?id=3624
可能对刚开始学习线程同步与互斥的人大有帮助
同时提供了一个Windows同步对象的单元,演示了队列,栈,动态数组的使用
需要源代码的,请留下 eMail
 
>>LiChaoHui
再次感谢!
我在看你的例子。
 
废话的代码基本没有,但是废话的注释可能比较多
如果看懂了,大家交流一下
参照一下
http://www.glcat.edu.cn/bmzy/dept2/czxt/3.htm
 
>>LiChaoHui
非常非常感谢!
我会向你学习的。
我的msn: mailto:zhenhuazhao@hotmail.com
 
后退
顶部