VCL 不是线程安全的。server.execute(...)
因此,我想在 INDY 10 TCP函数中将信息写入 gui 并不是一个好主意。
如何将信息从服务器执行发送到 VCL?
我需要在tcpserver.execute
函数中修改 TBitmap。如何使该线程安全?
从 Indy 向 VCL 线程写入内容的方式与从其他任何地方向 VCL 线程写入内容的方式相同。常见选项包括TThread.Synchronize
和TThread.Queue
。
修改一个独立的TBitmap
应该不需要与主线程同步。您可以从任何您想要的线程修改它,只要您一次只从一个线程进行修改。您可以使用标准同步对象(如临界区和事件)来确保一次只有一个线程使用它。
同步的最佳方式是创建和使用 TidNotify 后代。
使用适当的私有字段定义一个像这样的 tidnotify 后代和 vcl proc。
TVclProc= procedure(aBMP: TBitmap) of object;
TBmpNotify = class(TIdNotify)
protected
FBMP: TBitmap;
FProc: TVclProc;
procedure DoNotify; override;
public
constructor Create(aBMP: TBitmap; aProc: TVclProc); reintroduce;
class procedure NewBMP(aBMP: TBitmap; aProc: TVclProc);
end;
然后像这样实现它
{ TBmpNotify }
constructor TBmpNotify.Create(aBMP: TBitmap; aProc: TVclProc);
begin
inherited Create;
FBMP:= aBMP;
FProc:= aProc;
end;
procedure TBmpNotify.DoNotify;
begin
inherited;
FProc(FBMP);
end;
class procedure TBmpNotify.NewBMP(aBMP: TBitmap; aProc: TVclProc);
begin
with Create(aBMP, aProc) do
begin
Notify;
end;
end;
然后从
server.execute(...)
像这样称呼它
procedure TTCPServer.DoExecute(aContext: TIdContext);
var
NewBMP: TBitmap;
begin
TBmpNotify.NewBMP(NewBMP, FVclBmpProc);
end;
其中 FVclBmpPro 是一个私有字段,指向与 TVclProc 的参数签名匹配的表单上的过程。此字段应在创建之后和启动服务器之前通过服务器对象上的属性进行设置。
表单上的方法可以自由地使用它接收到的位图,而不必担心线程争用、死锁和其他通过访问 VCL 控件而不同步而产生的麻烦。
一个简单的 PostMessage(线程内)和处理消息(线程外)是进行 UI 更新所必需的......