VCL不是线程安全的。因此,我认为在Indy10tcp server.execute(...)函数中将信息写入gui不是一个好主意。
如何将信息从服务器执行发送到VCL?
我需要修改tcpserver.execute函数中的TBitmap。如何保证该线程的安全?
发布于 2012-10-24 02:29:20
从Indy向VCL线程写入数据的方式与从其他任何地方向VCL线程写入数据的方法相同。常见选项包括TThread.Synchronize和TThread.Queue。
修改独立的TBitmap不需要与主线程同步。您可以从任何线程修改它,只要一次只能从一个线程执行即可。您可以使用标准的同步对象,如临界区和事件,以确保一次只有一个线程使用它。
发布于 2012-10-24 23:26:07
最好的同步方式是创建并使用TidNotify后代。
使用适当的私有字段定义一个tidnotify子代和vcl进程,如下所示。
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;其中,FVclBmpProcis是一个私有字段,指向与TVclProc的参数签名匹配的表单上的过程。此字段应在创建后和启动服务器之前通过服务器对象上的属性进行设置。
窗体上的方法将可以自由地使用它接收到的位图,而不用担心线程争用、死锁和其他因访问VCL控件而不进行同步而造成的麻烦。
发布于 2012-12-20 19:32:27
一个简单的PostMessage (在线程内)和处理消息(在线程外)是进行UI更新所必需的……
https://stackoverflow.com/questions/13036579
复制相似问题