首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >德尔福XE6印度聊天室

德尔福XE6印度聊天室
EN

Stack Overflow用户
提问于 2014-08-24 03:26:44
回答 1查看 1.8K关注 0票数 0

我试着用TIdTCP!在网上建立聊天室

当客户端向服务器发送消息时,服务器将继续发送到其他客户端,下面是我的代码:

服务器

代码语言:javascript
复制
   var
  List: TIdContextList;
  Context: TIdContext;
  i: Integer;
  Msg: String;

Procedure TSForm.SendALL(text: string);
begin
  MSG:= Trim(text);
  List := Server.Contexts.LockList;
  try
    for i := 0 to List.Count - 1 do
    begin
      Context := TIDContext(List[i]);
      Context.Connection.IOHandler.WriteLn(UTF8Encode(msg));
    end;
  finally
    Server.Contexts.UnlockList;
  end;
end;

procedure TSForm.ServerExecute(AContext: TIdContext);
var m: string;
Begin
 m:= acontext.Connection.IOHandler.ReadLn();
  begin
   SForm.log.Lines.Add(Acontext.Connection.Socket.Binding.PeerIP+' > '+m); //Log is MEMO
   SendALL(m);
  end;
end;

和客户

代码语言:javascript
复制
type
 TReadingThread = class(TThread)
  protected
    FConn: TIdTCPConnection;
    procedure Execute; override;
    procedure DoTerminate; override;
  public
    constructor Create(AConn: TIdTCPConnection); reintroduce;
  end;

var readthread: TReadingThread = Nil;

constructor TReadingThread.Create(AConn: TIdTCPConnection);
begin
  FConn := AConn;
  inherited Create(False);
end;

procedure TReadingThread.Execute;
var
  cmd: string;
begin
  while not Terminated do
  begin
    cmd := UTF8ToUnicodeString(FConn.IOHandler.ReadLn());
    Trim(cmd);
    if cmd <> '' then
    begin
    CForm.Memo1.Lines.Add(cmd); //Memo1 to show messages
    end;
  end;
   Application.ProcessMessages;
end;

procedure TReadingThread.DoTerminate;
begin
  inherited;
end;

procedure TCForm.ClientConnected(Sender: TObject);
begin
 readthread:= TReadingThread.Create(Client);
end;

procedure TCForm.ClientDisconnected(Sender: TObject);
begin
    if  readthread<> nil then
  begin
    readthread.Terminate;
    readthread.WaitFor;
    FreeAndNil(readthread);
  end;
end;

一切看起来都很好,但是当服务器重新发送消息时,其他客户端得到消息并在备忘录中显示--通常是--除了发送消息的客户机(似乎冻结了)之外,必须单击备忘录才能显示文本!

我不知道哪里不对,希望能得到你的帮助,谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-24 04:00:36

您的代码有两处错误:

您正在从第二个线程访问VCL组件。这通常被认为是非常糟糕的,因为它可能导致许多不可忽视的问题。

代码语言:javascript
复制
procedure TReadingThread.Execute;
...
  CForm.Memo1.Lines.Add(cmd); //Verry bad as you are accesing VCL from another thread
...
  Application.ProcessMessages; //This is even worse. I suggest you get rid of this
...
end;

此外,摆脱Application.ProcessMessages,因为这只会导致更多的问题,它可以解决更多的问题,更不用说它对程序性能有很大的影响。

因此,在更新备忘录时,应该使用同步命令。这迫使更新备忘录的代码在主线程中执行,所有正在访问VCL的代码都应该执行。

代码语言:javascript
复制
procedure TReadingThread.Execute;
...
  Synchronize(
    procedure
    begin
      CForm.Memo1.Lines.Add(cmd);
    end;);
...
end;
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25468252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档