首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Indy10死锁在TCPServer

Indy10死锁在TCPServer
EN

Stack Overflow用户
提问于 2012-10-26 20:50:32
回答 3查看 789关注 0票数 1

将有关处理状态的信息写入tcpserver.onexecute(.)中的图形用户界面函数,我使用了以下命令序列

代码语言:javascript
复制
ExecuteDUMMYCommand(Global_Send_Record);

BitMap_PaintImageProcess;

TThread.Synchronize(nil, BitMap_PaintImageProcess);

这段代码在一些机器上运行良好,但在少数机器上却失败了。代码执行将停止atTThread.Synchronize命令。我想,在这些机器上,函数调用被困在死锁中,有机会找出背后的真正问题吗?

过程BitMap_PaintImageProcess,这里我创建了一个位图,做了很多绘画工作,但是这段代码似乎从来没有被执行过吗?

我试图解释非常长的代码,并将其简化为要点,关键的线程问题隐藏在处理Bitmapprocessingclass中的位图中。这个类是在我的GUIProcessing过程中访问的,my ServerMainForm也有INDY组件。

代码语言:javascript
复制
   {---------------   CLASS DEFINITION   -----------------------------}

   TBitMapProcessingClass = class()
        FBitmap : TBitmap;
        FList : TListOfSomething;

        procedure ProcessTheBitmap(....);
        ......   
        (many many functions);
        procedure Init;
        procedure Free;
        Procedure Create;
   end;


   TMainform = class(TForm)

      MyServer : TIdTCPServer;
      aBitMaoProcessingClass : TBitMaoProcessingClass;
      procedure BitMap_PaintImageProcess;
      procedure BitMap_ListProcess;

      .....
      end;       



{-------------------------   Implemantation ------------------------------}


procedure TMainform.IndyTCPServer.Onexecute()
begin

   .......

   ExecuteDUMMYCommand(Global_Send_Record);

   BitMap_PaintImageProcess;

   TThread.Synchronize(nil, BitMap_PaintImageProcess);

   .......


end;



procedure TMainform.BitMap_PaintImageProcess;
   begin

      DoSomeServerVCLStuff(....);

      aBitMapProcessingClass.ProcessTheBitmap;


      DoSomeServerVCLStuff(....);

  end;
EN

回答 3

Stack Overflow用户

发布于 2012-10-26 22:49:18

由于不知道BitMap_PaintImageProcess()实际上做了什么,我有几个假设:

  • 在TThread.Synchronize调用中,您尝试从套接字/idContext读取一些数据,但数据尚未可用。这将阻塞主线程,直到数据可用为止。但是,Indy的线程负责从底层套接字缓冲区读取数据,目前在TThread.Synchronize事件中被您的OnExecute调用所阻塞,即出现死锁;
  • 在TThread.Synchronize调用中,您使用Application.ProcessMessages (常见错误);
  • 在OnExecute事件中,输入一个关键部分。然后,在TThread.Synchronize调用期间,您再次尝试输入相同的关键部分;
  • 您可以在onExecute事件中修改GUI。因为onExecute不是线程安全的,所以从Indy的线程访问VCL/FM可能导致不可预测的结果,包括随机死锁(难以找到)。

我建议使用MadExcept / Eurekalog。它们都有检查主线程是否“冻结”的选项。当这种情况发生时(在死锁期间),它们将向您显示当前的调用堆栈。有了调用堆栈,就可以知道是哪个函数导致了死锁。

票数 0
EN

Stack Overflow用户

发布于 2012-10-27 10:30:25

关于张贴的代码:

代码语言:javascript
复制
procedure TMainform.IndyTCPServer.Onexecute()
begin
   .......
   ExecuteDUMMYCommand(Global_Send_Record);
   BitMap_PaintImageProcess; //-> You do VCL stuff in the context of Indy's thread!
   TThread.Synchronize(nil, BitMap_PaintImageProcess);
end;

BitMap_PaintImageProcess()中,您称为DoSomeServerVCLStuff(....)。不要忘记,OnExecute是从Indy的线程中为当前上下文触发的。也就是说,您从另一个线程(来自主线程的其他线程)修改VCL,该线程不是线程安全的。

关于你的评论:

...but这里我的复杂TBitmap处理类必须在我的服务器活动的整个时间内都是活动的.

如果您只有一个用于图像处理的(全局)实例,那么如果另一个客户端连接,而您仍然在处理旧的连接(想想并行:),会发生什么?对于每个新的连接/上下文,您的图像处理类应该分别实例化。对于GUI更新,您可以使用TIdNotify后代。

一种可能的解决办法:

代码语言:javascript
复制
type 
{ tIdNotify Stuff }
TVclProc= procedure(imgClass: tMyImageProcessingClass) of object;

tIdNotifyDescendant = (tIdNotify)
  protected
    fImgClass: tMyImageProcessingClass;
    fProc: TVclProc;
    procedure DoNotify; override;
  public
    class procedure updateVcl(imgClass: tMyImageProcessingClass; vclProc: TVclProc);
end;

procedure tIdNotifyDescendant.DoNotify;
begin
 inherited DoNotify;
 FProc(fImgClass);
end;

class procedure tIdNotifyDescendant.updateVcl(imgClass: tMyImageProcessingClass; vclProc: TVclProc);
begin
 with Create do
 begin
   fImgClass := imgClass;
   fProc := vclProc;
   Notify;
 end;
end;

{ Indy stuff & other logic }

procedure TForm1.IdTCPServer1Connect(AContext: TIdContext);
begin
  //  Create your instance when the client connects
  AContext.Data := tMyImageProcessingClass.Create;
end;

procedure TForm1.IdTCPServer1Disconnect(AContext: TIdContext);
begin
  //  Do cleanup
  if assinged(AContext.Data) then
    (AContext.Data as tMyImageProcessingClass).Free // Casting just for clarity
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
  imgProcClass: tMyImageProcessingClass;
begin
  imgProcClass := acontext.Data as tMyImageProcessingClass;
  //  Do image processing
  //  Notify GUI for the progress:
  tIdNotifyDescendant.updateVcl(AContext.data as tMyImageProcessingClass);
end;

提示:如果您做了JPEG处理,并且使用了TJPEGImage.Draw()不是线程安全的 ()方法,请记住以下内容:

票数 0
EN

Stack Overflow用户

发布于 2012-10-28 10:19:17

我对我的BitmapProcessingclass和现有类的线程安全扩展的想法添加了更多的细节.我需要你在其他应用中改变现有的类.我需要一个扩展在我的应用程序与印第服务器。ONly一个客户端我连接到一个服务器,或者他必须查询服务器的状态。

代码语言:javascript
复制
    type TBmpNotify = class(TIdNotify)
   protected
     FBMP: MyImageProcessingClass;

     procedure DoNotify; override;
   public
     constructor Create(aBMP: MyImageProcessingClass);
       function SetImageView(LL, UR: TPoint): Boolean;
              procedure PaintBitMap;
      function InitBitMap(x, y: Integer;
         PixelFormat: TPixelFormat = pf24bit): Boolean;
      destructor free;
   end;


   implementation

   { TBmpNotify }

   constructor TBmpNotify.Create(aBMP: MyImageProcessingClass);
   begin
       //   indise this class  I also create
       //   class.TBitmap
       //   class.TList
       //   much more stuff ....
       FBmp := MyImageProcessingClass.Create;
   end;

   procedure TBmpNotify.DoNotify;
   begin
     inherited;

   end;

   destructor TBmpNotify.free;
   begin

       FBmp.Free;

       inherited;
   end;

   function TBmpNotify.InitBitMap(x, y: Integer;
     PixelFormat: TPixelFormat): Boolean;
   begin
       //   Write values to the List
       //   also modify TBitmap
       //   execution time of this function ~ 5 min
       FBmp.InitBitMap(x,y,PixelFormat)
   end;

   procedure TBmpNotify.PaintBitMap;
   begin
       //   much TBitmap, bitmap.canvas .... is used
       //   execution time of this function ~ 1  min
      FBmp.PaintBitMap;
   end;

   function TBmpNotify.SetImageView(LL, UR: TPoint): Boolean;
   begin
      //  this function takes about 1 min
      FBmp.SetImageView(LL, UR);
   end;

   end.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13094245

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档