INDY 10 TCP服务器-与非线程安全的VCL代码结合使用

5

VCL不支持多线程,因此我认为在INDY 10 TCP server.execute(...)函数中写入GUI信息不是一个好主意。

如何从server execute发送信息到VCL?

我需要在tcpserver.execute函数内修改TBitmap。如何做到线程安全?

3个回答

4
使用Indy向VCL线程中写入内容的方法与从任何其他地方向VCL线程中写入内容的方法相同。常见的选项包括 TThread.SynchronizeTThread.Queue
修改独立的TBitmap不需要与主线程同步。只要您在一次只有一个线程中修改它,就可以从任何想要的线程中进行修改。您可以使用标准的同步对象(如关键部分和事件),以确保只有一个线程同时使用它。

TIdNotify.NotifyMethod 是异步运行的,因为它仅仅调用了 TThread.Queue。难道你尝试做的事情中有 20% 需要同步访问 VCL 吗? - Rob Kennedy
需要一个简单的示例副本,说明如何使用TIdsync完成此操作,这是解决方案吗? - user1769184
找到了https://dev59.com/fmfWa4cB1Zd3GeqPktKJ,我真的应该在这个类中编写vcl代码吗? - user1769184
我使用 Delphi XE2。在我的 TIdNotify.NotifyMethod(ShowStartServerMessage) 函数中,只有简单的 VCL 访问,例如 Memo1.Lines.add(Global_section_strings);如何同步 VCL 活动? - user1769184
感谢您的帮助;现在我已经将 TIdNotify.NotifyMethod(ShowStartServerMessage) 添加到代码中,该行代码为: TThread.Synchronize(nil, ShowStartServerMessage); 我猜问题现在已经解决了。 - user1769184
显示剩余5条评论

2

最佳同步方式是创建并使用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;

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

表单上的方法将可以自由使用接收到的位图,而不用担心线程争用、死锁和其他访问VCL控件时出现的问题,因为它们没有同步。


谢谢Mike,我会在我的程序中测试那段代码;现在在stackoverflow上有很多Delphi和INDY 10的有用代码片段;有人应该把它们复制到电子书中 :-) - user1769184

1

只需要一个简单的PostMessage(在线程内部)和处理消息(在线程外部),就可以进行UI更新...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接