VCL不是线程安全的。因此,我想在INDY 10 TCP server.execute(...)
函数中向gui写入信息并不是一个好主意。INDY 10 TCP服务器 - 结合非线程安全VCL代码
如何从服务器执行信息发送到VCL?
我需要修改tcpserver.execute
函数中的TBitmap。如何使线程安全?
VCL不是线程安全的。因此,我想在INDY 10 TCP server.execute(...)
函数中向gui写入信息并不是一个好主意。INDY 10 TCP服务器 - 结合非线程安全VCL代码
如何从服务器执行信息发送到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;
然后从那里FVclBmpProcis一个私有字段指向程序
server.execute(...)
这样称呼它
procedure TTCPServer.DoExecute(aContext: TIdContext);
var
NewBMP: TBitmap;
begin
TBmpNotify.NewBMP(NewBMP, FVclBmpProc);
end;
在表格上hat匹配TVclProc的参数签名。该字段应该在创建之后和启动服务器之前通过服务器对象上的属性进行设置。
表单上的方法可以自由使用它接收到的位图,而不用担心通过访问VCL控件创建的线程争用,死锁和其他缺陷而无需同步。
感谢Mike,我将在我的程序中测试该代码; Delphi和INDY 10的stackoverflow上现在有许多有用的代码sniplets;有人应该将其复制到E书:-) – user1769184
一个简单的PostMessage的(线程内)和处理消息(线程外)是必要的,使UI更新...
我做了Id.notify梅索德调用内部的所有VCL的东西,但只适用80%成功... – user1769184
[code] procedure TServerMainForm.IdTCPServerExecute(AContext:TIdContext); var .... begin /// /// TIdNotify.NotifyMethod(ShowStartServerMessage); ...... – user1769184
'TIdNotify.NotifyMethod'异步运行,因为它只不过是调用'TThread.Queue'。难道20%你想要做的事情需要同步访问VCL吗? –