将有关处理状态的信息写入tcpserver.onexecute(.)中的图形用户界面函数,我使用了以下命令序列
ExecuteDUMMYCommand(Global_Send_Record);
BitMap_PaintImageProcess;
TThread.Synchronize(nil, BitMap_PaintImageProcess);这段代码在一些机器上运行良好,但在少数机器上却失败了。代码执行将停止atTThread.Synchronize命令。我想,在这些机器上,函数调用被困在死锁中,有机会找出背后的真正问题吗?
过程BitMap_PaintImageProcess,这里我创建了一个位图,做了很多绘画工作,但是这段代码似乎从来没有被执行过吗?
我试图解释非常长的代码,并将其简化为要点,关键的线程问题隐藏在处理Bitmapprocessingclass中的位图中。这个类是在我的GUIProcessing过程中访问的,my ServerMainForm也有INDY组件。
{--------------- 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;发布于 2012-10-26 22:49:18
由于不知道BitMap_PaintImageProcess()实际上做了什么,我有几个假设:
我建议使用MadExcept / Eurekalog。它们都有检查主线程是否“冻结”的选项。当这种情况发生时(在死锁期间),它们将向您显示当前的调用堆栈。有了调用堆栈,就可以知道是哪个函数导致了死锁。
发布于 2012-10-27 10:30:25
关于张贴的代码:
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后代。
一种可能的解决办法:
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()不是线程安全的 ()方法,请记住以下内容:
发布于 2012-10-28 10:19:17
我对我的BitmapProcessingclass和现有类的线程安全扩展的想法添加了更多的细节.我需要你在其他应用中改变现有的类.我需要一个扩展在我的应用程序与印第服务器。ONly一个客户端我连接到一个服务器,或者他必须查询服务器的状态。
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.https://stackoverflow.com/questions/13094245
复制相似问题