Заголовок формы IdHttpServer не обновляется - PullRequest
1 голос
/ 20 марта 2012

Я знаю, что уже писал подобный вопрос, но не могу заставить его работать. У меня есть простой код:

procedure TfrmMain.srvrConnect(AContext: TIdContext); //idhttpserver on connect event
var
  S,C : String;
begin
 repeat
  s := s + AContext.Connection.Socket.ReadChar;
 until AContext.Connection.Socket.InputBufferIsEmpty = True;
 frmMain.caption := S;
 Memo1.Lines.Add(S);
end;

Строки отображаются нормально в заметке, но заголовок не обновляется

Ответы [ 2 ]

3 голосов
/ 21 марта 2012

TIdHTTPServer - многопоточный компонент. TIdContext работает в своем собственном рабочем потоке. Вы не можете безопасно обновлять Caption формы (или делать что-либо еще с пользовательским интерфейсом) из-за пределов основного потока. Вам необходимо выполнить синхронизацию с основным потоком, например с классом TIdSync или TIdNotify.

Кстати, вызов ReadChar() в цикле очень неэффективен, не говоря уже о подверженности ошибкам, если вы используете Delphi 2009+, поскольку он не может возвращать данные для суррогатных пар.

Вместо этого используйте что-то более подобное;

type
  TDataNotify = class(TIdNotify)
  protected
    Data: String;
    procedure DoNotify; override;
  public
    constructor Create(const S: String);
    class procedure DataAvailable(const S: String);
  end;

constructor TDataNotify.Create(const S: String);
begin
  inherited Create;
  Data := S;
end;

procedure TDataNotify.DoNotify;
begin
  frmMain.Caption := Data; 
  frmMain.Memo1.Lines.Add(Data); 
end;

class procedure TDataNotify.DataAvailable(const S: String);
begin
  Create(S).Notify;
end;

procedure TfrmMain.srvrConnect(AContext: TIdContext); //idhttpserver on connect event 
var 
  S: String; 
begin 
  AContext.Connection.IOHandler.CheckForDataOnSource(IdTimeoutDefault);
  if not AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    S := AContext.Connection.IOHandler.InputBufferAsString; 
    TDataNotify.DataAvailable(S); 
  end;
end; 
1 голос
/ 20 марта 2012

Сначала убедитесь, что вы пишете в нужную переменную. Вы уверены, что frmMain - это та форма, которую вы хотите изменить?

Также вы можете попробовать:

procedure TfrmMain.srvrConnect(AContext: TIdContext); //idhttpserver on connect event
var
  S,C : String;
begin
 repeat
  s := s + AContext.Connection.Socket.ReadChar;
 until AContext.Connection.Socket.InputBufferIsEmpty = True;
 oCaption := S;
 TThread.Synchronize(nil, Self.ChangeCaption);
end;

procedure TfrmMain.ChangeCaption;
begin
 Self.Caption := oCaption;
 Memo1.Lines.Add(oCaption);
end;

И, наконец, убедитесь, что первая строка в S не является пустой строкой, поскольку заголовок формы не будет отображать строки, содержащие перевод строки.

...