简体   繁体   English

Delphi XE6 Indy聊天室

[英]Delphi XE6 Indy Chat Room

I am trying to make chat room over Internet with TIdTCP! 我正在尝试使用TIdTCP在Internet上建立聊天室!
When the client send message to server , server will continue to send to other clients , here my code: 客户端服务器发送消息时,服务器将继续向其他客户 发送消息,这是我的代码:

Server 服务器

   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;

And Client 和客户

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;

Everything looks fine, but when Server resend the messages, other clients get it and show in memo normally except The Client which send that message seems freeze, must click to memo to make the text show up! 一切看起来都很好,但是当服务器重新发送消息时,其他客户端会正常接收并显示在备忘录中,但发送该消息的客户端似乎冻结了, 必须单击备忘录以显示文本!

I don't know what wrong place, hope to get help from you, Thanks! 我不知道哪里出了错,希望得到您的帮助,谢谢!

There are two things wrong with your code: 您的代码有两件事:

You are accesing VCL components from second thread. 您正在从第二个线程访问VCL组件。 This is generally considered verry bad as it could lead to lots of unforseen problems. 通常认为这很糟糕,因为它可能导致许多无法预料的问题。

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;

Also get rid of Application.ProcessMessages as this could only cause more problems that it solves not to mention that it greatly affects the programs performance. 还要摆脱Application.ProcessMessages,因为这只会导致解决更多的问题,更不用说会严重影响程序的性能。

So you should use Synchronize command when updating memo. 因此,更新备忘录时应使用“同步”命令。 This forces code for updating memo to execute in main thread as all code that is accesing VCL should. 这将强制更新备忘录的代码在主线程中执行,就像要访问VCL的所有代码一样。

procedure TReadingThread.Execute;
...
  Synchronize(
    procedure
    begin
      CForm.Memo1.Lines.Add(cmd);
    end;);
...
end;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM