关于delphi线程同步的实例(教材上没有,作该文之前网上也没有)

导读:
   (原创)关于delphi线程同步的实例(教材上没有,作该文之前网上也没有)
  三、 通过事件同步主线程与从线程的实例
  ▲ 实例定义了一个主类: Tlistfile。该类主要是根具recmail变量,把它存入一个文件或从一个文件中读取出来。在该类上可实现:两个或多个应用程序之间通过文件进行异步问答式通讯。所谓问答式异步通讯是:一个程序发问,只有等到其他程序回答后才能继续发问。在一个时刻只能有一个程序使用该通讯文件,并且发送信息时必须进快完成。
  ▲该类约定了存取所用的文件是同一个文件且存在。
  ▲存recmail变量用savereclist方法,读recmail用loadreclist方法。
  ●savereclist方法实现:用TsaveThread线程实现。
  当外界调用savereclist方法时,该方法首先创建一个TsaveThread线程,然后运行它,由它完成存取文件的操作,接着挂起主线程,等等TsaveThread线程执行完毕,TsaveThread线程执行完毕唤醒主线程。为了防止多个TsaveThread线程之间的干扰,在TsaveThread线程内用了临界区同步变量进行线程同步。
  ●loadreclist方法实现:用TloadThread线程实现。
  当外界调用loadreclist方法时,该方法首先创建一个TloadThread线程,然后运行它,由它完成读取文件的操作,接着挂起主线程,等等TloadThread线程执行完毕,TloadThread线程执行完毕唤醒主线程。为了防止多个TloadThread线程之间的干扰,在TloadThread线程内用了临界区同步变量进行线程同步。
  unit listfile;
  interface
  uses Classes,SysUtils,StrUtils,ExtCtrls,SyncObjs,Dialogs,windows;
  type
  precmail =^trecmail;
  Trecmail =record
  subject :string[150];//异步通信内容
  recDate :tdatetime;//通信时时间
  askBL,answerSBL,answerFBL :boolean;//定义了文件的问、开始回答、回答完毕标识。
  end;
  TlistFile=class //主类
  public
  recmail:Trecmail;
  constructor create(filename:string);//创建时获得通讯文件名
  procedure savereclist();
  procedure loadreclist();
  destructor destroy;
  end;
  TLoadThread=class(TThread) //读取线程
  protected
  Procedure Execute;override;
  end;
  TSaveThread=class(TThread)式//存取线程
  protected
  Procedure Execute;override;
  end;
  function IsFileInUse(fName : string ) : boolean;//文件在用检测函数
  var
  srecmail:Trecmail;//读存线程与主线程的recmail通信所用的变量
  sfilename:string;// 异步通讯文件变量
  Critical1,Critical2:TCriticalSection;//分别是读线程、存线程同步所用的临界变量
  sevent1,sevent2:tsimpleEvent; /分别是读线程与主线程、存线程与主线程同步所用的同步事件变量
  implementation
  function IsFileInUse(fName : string ) : boolean;
  var
  HFileRes : Tfilestream;
  begin
  Result := false;
  if not FileExists(fName) then
  exit;
  try
  hfileres:=Tfilestream.create(fname,fmShareExclusive);
  result:=false;
  except
  result:=true;
  end;
  try
  hfileres.Free;
  except
  end;
  end;
  procedure TLoadThread.Execute;//读线程的执行代在码
  var
  fl:file of trecmail; loadBL:boolean;
  begin
  Critical1.Enter ;//临界区同步开始
  loadBL:=true;
  while true do //循环的原因是当通信文件还在使用是就不停的等待,直到可以使用该文件
  begin
  if not (IsFileInUse(sfilename)) then
  begin
  if not loadBL then
  begin
  Critical1.Leave ;
  sevent1.SetEvent ;//唤醒挂起的主线程
  exit;
  end else
  begin
  AssignFile(fl,sfilename);
  reset(fl);
  read(fl,srecmail);
  closefile(fl);
  loadBL:=false;
  end;
  end;
  end;
  Critical1.Leave ;//临界区同步结束
  end;
  procedure TSaveThread.Execute;// 存线程的执行代在码
  var
  fl:file of trecmail; saveBL:boolean;
  begin
  Critical2.Enter ;//临界区同步开始
  saveBL:=TRUE;
  while true do //循环的原因是当通信文件还在使用是就不停的等待,直到可以使用该文件
  begin
  if (not IsFileInUse(sfilename)) then
  begin
  if not saveBL then
  begin
  Critical2.Leave ;
  sevent2.SetEvent ;//唤醒挂起的主线程
  exit;
  end else
  begin
  AssignFile(fl,sfilename);
  rewrite(fl);
  write(fl,srecmail);
  closefile(fl);
  saveBL:=false;
  end;
  end;
  end;
  Critical2.Leave ;//临界区同步结束
  end;
  constructor TlistFile.create(filename:string);
  begin
  sfilename:= filename;//得到同步文件名
  Critical1:= TCriticalSection.Create ;//创建读临界区同步对象
  Critical2:= TCriticalSection.Create ;//创建存临界区同步对象
  end;
  procedure TlistFile.savereclist();//存文件操作
  var
  saveThread:TSaveThread;
  begin
  srecmail:=recmail ;//得存文件时,存线程要用到的要存通讯数据
  sevent2:=TSimpleEvent.Create ;//创建与存线程同步所用的同步事件对象
  sevent2.ResetEvent;//此处决定了该事件操纵的线程是主线程,因为第一次调用它的是主线程。
  //用了该方法后,再用WaitFor(INFINITE);时,主线程将被挂起
  saveThread:= TSaveThread.create(true);//创建存线程对象,创建后不立即执行。
  saveThread.FreeOnTerminate :=true;//此处是当存线程执行完毕后自动灭亡,并释放资源。
  saveThread.Resume;//唤醒存线程让之运行,以执行存文件任务
  sevent2.WaitFor(INFINITE);//主线程被挂起,直到存线程执行完毕唤醒它
  sevent1.Release ;//释放sevent2所用到的资源
  end;
  procedure TlistFile.loadreclist();//读文件操作
  var
  LoadThread:TLoadThread;
  begin
  sevent1:=TSimpleEvent.Create ;// 创建与读线程同步所用的同步事件对象
  sevent1.ResetEvent; //此处决定了该事件操纵的线程是主线程,因为第一次调用它的是主线程。
  //用了该方法后,再用WaitFor(INFINITE);时,主线程将被挂起
  LoadThread:= TLoadThread.create(true); //创建读线程对象,创建后不立即执行。
  LoadThread.FreeOnTerminate :=true;
  loadThread.Resume ;//唤醒读线程让之运行,以执行读文件任务
  sevent1.WaitFor(INFINITE); //此处是当读线程执行完毕后自动灭亡,并释放资源。
  recmail:=srecmail ;//主线程得到读线程读到的通讯数据,以使文件通过recmail访问
  sevent1.Release ;//释放sevent1所用到的资源
  end;
  destructor TlistFile.destroy;
  begin
  inherited destroy;
  Critical1.Destroy ;
  Critical2.Destroy ;
  end;
  end.
  本帖最近评分记录
  softwolf中天币 +20我很赞同2006-3-11 07:13
   TOP

本文转自
http://bbs.366tian.net/thread-273358-1-1.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值