5

VCL 不是线程安全的。server.execute(...) 因此,我想在 INDY 10 TCP函数中将信息写入 gui 并不是一个好主意。

如何将信息从服务器执行发送到 VCL?

我需要在tcpserver.execute函数中修改 TBitmap。如何使该线程安全?

4

3 回答 3

4

从 Indy 向 VCL 线程写入内容的方式与从其他任何地方向 VCL 线程写入内容的方式相同。常见选项包括TThread.SynchronizeTThread.Queue

修改一个独立的TBitmap应该不需要与主线程同步。您可以从任何您想要的线程修改它,只要您一次只从一个线程进行修改。您可以使用标准同步对象(如临界区和事件)来确保一次只有一个线程使用它。

于 2012-10-23T18:29:20.467 回答
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;

其中 FVclBmpPro 是一个私有字段,指向与 TVclProc 的参数签名匹配的表单上的过程。此字段应在创建之后和启动服务器之前通过服务器对象上的属性进行设置。

表单上的方法可以自由地使用它接收到的位图,而不必担心线程争用、死锁和其他通过访问 VCL 控件而不同步而产生的麻烦。

于 2012-10-24T15:26:06.923 回答
1

一个简单的 PostMessage(线程内)和处理消息(线程外)是进行 UI 更新所必需的......

于 2012-12-20T11:32:26.593 回答