VCL不是线程安全的。因此,我想在INDY 10 TCP server.execute(...)
函数中将信息写入gui不是一个好主意。
如何从服务器发送信息执行到VCL?
我需要修改tcpserver.execute
函数内的TBitmap。如何使该线程安全?
答案 0 :(得分:4)
以相同的方式将东西写入Indy的VCL线程,以便从其他任何地方将东西写入VCL线程。常见选项包括TThread.Synchronize
和TThread.Queue
。
修改独立TBitmap
不应要求与主线程同步。您可以从任何所需的线程修改它,只要您一次只从一个线程执行。您可以使用标准同步对象(如关键部分和事件)来确保一次只有一个线程使用它。
答案 1 :(得分:2)
同步的最佳方式是创建和使用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;
其中FVclBmpProc是一个私有字段,指向窗体上与TVclProc的参数签名匹配的过程。应该在创建之后和启动服务器之前通过服务器对象上的属性设置此字段。
表单上的方法可以自由使用它接收到的位图,而不用担心线程争用,死锁以及通过访问VCL控件而不同步而产生的其他恶意。
答案 2 :(得分:0)
一个简单的PostMessage(在线程内)和处理消息(在线程外)是进行UI更新所必需的......