首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

线程,太伤人了!该如何解决

2013-06-25 
线程,太伤人了!!!!!!各位大大,我把控制线程启动和挂起的操作写在一个Timer的Ontimer事件中,在消费时间内启

线程,太伤人了!!!!!!
各位大大,我把控制线程启动和挂起的操作写在一个Timer的Ontimer事件中,在消费时间内启动线程,不在消费时间内则挂起线程,等待下次在消费时间内再Resume,ZQ_Consume_MealRoom 表中有三个分组,通过线程数组创建三个监控线程。
现在的问题来了,第一个和第二个线程Suspend后,第三个线程也不工作了(第三个还是在消费时间内的),等到第一个和第二个Resume后,第三个又可以正常运行了,问题点找不到,太受伤了。
onTimer代码如下 :

procedure Tfrmrealtime.StartTimerTimer(Sender: TObject);
var
  QY: TADOQuery;
  Code: integer; //用于判断是否在消费时段的变量;
  i: Integer;
begin
//RoomCode,Tag 两个一维数组,RoomCode用于保存监控组编号;Tag用于保存启动标识 :Jeff 2013.04.28
  i := 0;
  QY := TADOQuery.Create(self);
  QY.Connection := DMDM.CONN;
  with QY do
    begin
      Close;
      SQL.Clear;
      SQL.Add(' select RoomCode from ZQ_Consume_MealRoom ');
      try
        Open;
      except
        ExecSQL;
      end;
      while not Eof do
        begin
          if not SameText(RoomID[i],FieldByName('RoomCode').AsString) then
            RoomID[i] := FieldByName('RoomCode').AsString;
          Code := DMDM.F_IsMealConsumeTime(FieldByName('RoomCode').AsString, FormatDateTime('hh:nn', Now));
          if Code = 0 then
            begin
              if Tags[i] <> -1 then
                begin
                  Tags[i] := -1;
                  p_Logs('监控组:[' + FieldByName('RoomCode').AsString + ']不在消费时段,监控结束.', true);
                  if CheckThreadFreed(RunThread[i])=1 then
                    begin
                      RunThread[i].Suspend;//线程挂超 Jeff 2013.04.30
                    end;
                end;
            end
          else
            begin
              if Tags[i] <> 1 then
                begin
                  Tags[i] := 1;
                  Kind[i] := Code;


                  p_Logs('监控组:[' + FieldByName('RoomCode').AsString + ']启动.', False);
                  DMDM.OpenConsume(RoomID[i], FormatDateTime('ddddd', Now),Kind[i]);
                  //给监控对像的成员变量赋值 Jeff 2013.04.30
                  RoomGroup[i]:=TRoomGroup.Create;
                  RoomGroup[i].RoomCode := RoomID[i];
                  RoomGroup[i].TimeStr := FormatDateTime('ddddd', Now);
                  RoomGroup[i].Code := Kind[i];

                  RunThread[i].Resume;//线程启动 Jeff 2013.04.30
                  ToolButton2.Caption := '停止监控';
                  //sleep(1000);
                end;
            end;
           i := i+1;
          //当前时间与当前分组的消费时段进行比对;
          Next;
        end;
    end;
    QY.Destroy;
end;




线程代码如下:
unit Define;

interface

uses
  Classes,Forms,Controls,Windows,comctrls,stdctrls,EastRiver, EastRiverD,Sysutils,grids,Dialogs;

type

//定义监控组线程对象
  TRunThread = class(TThread)
     private
     protected
        procedure RuningRoom; //线程监控分组运行
        procedure Runing(RoomGroupID:Integer); //线程监控分组运行
        procedure Execute; override;
    public
        RoomGroupID:Integer;
  end;


//定义监控分组对象
  TRoomGroup = class
     private
     protected
     public
       RoomCode:String;                  //分组号
        TimeStr:String;              //监控日期
        Code:integer;        //当前监控分组的餐别
     Procedure Continuerun(RoomGroupID:Integer);  //继续运行
  end;
var
   RoomGroup:array[0..9] of TRoomGroup;    //监控分组实例对象
   RunThread:array[0..9] of TRunThread;  //运行控分组线程实例对象


   CS: TRTLCriticalSection;//多线程临界区定义
   RealRec:TRealRecordInfo;

implementation

uses realtime, DM, FuncPassWord;

{ TRunThread }

procedure TRunThread.Execute;
begin
  while not self.Terminated DO
    begin
      // Synchronize(RuningRoom);
       EnterCriticalSection(CS);
       try
         RuningRoom;
       finally
       LeaveCriticalSection(CS);
       end;
      // sleep(50);
    end;
end;

procedure TRunThread.Runing(RoomGroupID:Integer);
begin
   RoomGroup[RoomGroupID].Continuerun(RoomGroupID);
  // Application.ProcessMessages;
end;

procedure TRunThread.RuningRoom;
begin
  Runing(RoomGroupID);
end;

{ TRoomGroup }

procedure TRoomGroup.Continuerun(RoomGroupID:Integer);
var
  i: Integer;
  CID: integer;
begin
  for i:=0 to DMDM.DeviceStrList[RoomGroupID].Count-1 Do
    begin
      CID := StrToInt('$'+DMDM.DeviceStrList[RoomGroupID].Strings[i]);
      frmrealtime.Label5.Caption := '正在等待消费机:[' + DMDM.DeviceStrList[RoomGroupID].Strings[i] + ']最后一次刷卡...';
      //frmRealTime.p_Logs('正在等待消费机:[' + DMDM.DeviceStrList[RoomGroupID].Strings[i] + ']最后一次刷卡...', false);
      if RealReadRecord(frmRealTime.hPort,CID,@RealRec) then
        begin
          if RealRec.NoCard then
            //frmRealTime.p_Logs('消费机:[' + IntToStr(CID) + ']上没有卡片...', false)
          else
            begin
              if RealRec.Consume <> 0 then
                begin
                  frmRealTime.CurMoney := frmRealTime.CurMoney - RealRec.Consume;
                  EastRiverD.RealFeedback(frmRealTime.hPort,CID,frmRealTime.CurMoney,-1, 0)
                end
              else
                EastRiverD.RealFeedback(frmRealTime.hPort,CID,frmRealTime.CurMoney,-1, 0);
            end;
        end;
     // else
     //   frmRealTime.p_Logs('消费机:[' + IntToStr(CID) + ']不在线...', false);
    end;



end;



end.


[解决办法]
StartTimerTimer事件中的“RunThread[i].Suspend;//线程挂超 Jeff 2013.04.30”要改掉;因为你的RunThread中用到了临界值,每个子线程RunThread[i]执行都会进一次临界值,举个例子,当RunThread[0]取得访问CS的权力时(即调用了EnterCriticalSection(CS)),其他子线程就处于等待访问CS的状态,这个时候假如你调用了RunThread[0].Suspend,RunThread[0]就暂停了,但RunThread[0]还没有执行完RuningRoom;也就不会执行到LeaveCriticalSection(CS),这个时候所有线程都挂起在那,等待访问CS的状态。

你可以这么改:

新建一个变量和两个个方法用于控制线程的停止和启动:

TRunThread = class(TThread)
     private
       FStop: Boolean;
     protected
        procedure RuningRoom; //线程监控分组运行
        procedure Runing(RoomGroupID:Integer); //线程监控分组运行
        procedure Execute; override;
    public
        RoomGroupID:Integer;
  end;

procedure TRunThread.Stop;
begin
  FStop := True;
end;

procedure TRunThread.Start;
begin
  FStop := False;
  Resume;
end;

procedure TRunThread.Execute;
begin
  FStop := False;
  while not self.Terminated DO
    begin
      // Synchronize(RuningRoom);
       EnterCriticalSection(CS);
       try
         RuningRoom;
       finally
       LeaveCriticalSection(CS);
       end;
      // sleep(50);

       if FStop then
         Suspend;
    end;
end;

热点排行