2012-03-20 2 views
1

Я знаю, что я отправил подобный вопрос раньше, но я не смог получить его работу у меня есть этот простой код:IdHttpServer форма заголовок не обновляя

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; 

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

+1

IIRC IdHTTPServer в чтение/запись должна размещаться внутри контекста, так что вам нужно создать подкласс TIdContext, который будет обрабатывать запрос/ответ в теме, созданной на сервере, и от того, что вы можете сделать что вам нужно сделать, вот небольшая демонстрация, которую я написал некоторое время назад http://www.delphigeist.com/2010/12/dynamic-web-pages-with-dwscript-and.html – ComputerSaysNo

ответ

3

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; 
+0

wierd, но я ничего не получаю с AContext.Connection.IOHandler.InputBufferAsString; если я использую то, что я написал, он отлично работает ... любая идея, почему? – opc0de

+0

'InputBufferAsString' принимает все, что находится в' InputBuffer', и преобразует его в 'String'. На D2009 +, который включает в себя декодирование байтов в Unicode. Если это декодирование завершается неудачно, например, если байты содержат неполные последовательности символов, это может привести к возврату пустой строки. Внутренне декодирование основано на классах «TEncoding» Embarcadero, и эти классы не создают исключений при ошибках декодирования. Итак, реальный вопрос: какие данные вы пытаетесь получить в первую очередь, и почему вы пытались прочитать его по 1 символу за раз? –

+0

Я получаю данные от gps, поэтому строка не закодирована, как ascii – opc0de

1

Во-первых, убедитесь, что вы пишете нужную переменную. Вы уверены, что 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 не пустая строка, потому что подпись формы не будет показывать строки, которые содержат строки.

+0

Вы не можете безопасно обновлять пользовательский интерфейс от рабочий поток (в котором запущен 'TIdContext'), а' Application.ProcessMessages() 'не обновляет основной пользовательский интерфейс при вызове из рабочего потока. –

+0

@RemyLebeau, вы правы. Я собираюсь изменить его. –

+0

'TForm' не имеет метода' Synchronize() ', а' ChangeCaption() 'не является членом класса' TfrmMain'. Я обновил ваш ответ. –

Смежные вопросы