Delphi простой TCP-сервер зависает. Форма зависает, но сервер продолжает управлять клиентами - PullRequest
2 голосов
/ 23 апреля 2010

Я использую форму с IdTCPServer для управления строками от клиента с системой AThread.connection.readln / writeln. Обработка строк работает, и это не проблема.

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

Пожалуйста, помогите.

procedure TMonitorFrm.ServerExecute(AThread: TIdPeerThread);

    procedure post(PostMessage:string);
    begin
            try
                    AThread.Connection.WriteLn(PostMessage);
            except
                    showmessage('Cannot post');
            end;
    end;

var
        ActClient       : PClient;
        sTemp,
        CommBlock,
        NewCommBlock,
        ReceiverName,
        sContent,
        sSQL,
        sCommand        : String;
        iCount2,
        iCount          : Integer;

        sldb    : TSQLiteDatabase;
        sltb    : TSQLiteTable;

begin
        if not AThread.Terminated and AThread.Connection.Connected then
        begin
                CommBlock := AThread.Connection.ReadLn();
                ActClient := PClient(AThread.Data);
                ActClient.LastAction := Now;
                sCommand := copy(CommBlock,0,pos(',',CommBlock)-1); {seperate command}
                sContent := copy(CommBlock,pos(',',CommBlock)+1,length(CommBlock)-(pos(',',CommBlock)+1)); {seperate data block}
                iCount:= 0 ;

            if sCommand = 'Announce' then //SPECIAL
            begin
                    { Do stuff for this command...}
            end

            else if sCommand = 'CheckSect' then
                    {Etcetera...}

procedure TMonitorFrm.FormCreate(Sender: TObject);
var
        sCompetitionID  : string;
        sldb    : TSQLiteDatabase;
        sltb    : TSQLiteTable;
begin
        Clients := TThreadList.Create;
        Server.Active := True;
        AreaPnlList := TComponentList.Create;
        SectionPnlList := TComponentList.Create;
        Repeat until InputQuery('Competition Select', 'Please type the ID of the competition', sCompetitionID);
        iCompetitionID:=StrToInt(sCompetitionID);
        OpenDatabase(slDb);
        sltb:=slDb.GetTable('SELECT * FROM SectionTable WHERE CompetitionID='+sCompetitionID);
        Frame31.CreateSections(sltb,Frame31);
        sltb.Free;
        CloseDatabase(slDb);
{
This section needs to check the SQLite databases for sections and list them in the display window and makes a drag n drop profile...
}
end;

Ответы [ 4 ]

6 голосов
/ 23 апреля 2010

Indy использует блокирующие розетки. предполагается , чтобы повесить текущий поток. Чтобы использовать компоненты Indy в потоке VCL, в то же время оставляя поток VCL отзывчивым, добавьте в форму компонент TIdAntifreeze. Компоненты Indy знают об этом компоненте и будут периодически отдавать ему управление, чтобы ваш поток VCL мог продолжать обработку сообщений.

4 голосов
/ 23 апреля 2010

Если вы считаете, что не можете надежно отследить выполнение с помощью отладчика, вы можете добавить некоторую явную информацию о трассировке в свой код .
Использовать OutputDebugString для регистрации информации либо в IDE EventLog при запускеиз IDE или в окно DbgView (из SysInternals) при работе вне Delphi.

0 голосов
/ 27 апреля 2010

Это как остановить Readln, заставляя его зависать.Вы должны проверить, есть ли что-то там, чтобы прочитать сначала.Есть несколько способов сделать это, вы можете установить тайм-аут на чтение

Repeat
    CommBlock := '';
    CommBlock := AThread.Connection.ReadLn('',10);
    Application.ProcessMessages;
until Commblock <> '';

Или вы можете проверить, является ли соединение читаемым, перед попыткой чтения.

Repeat
    CommBlock:='';
    if AThread.Connection.IOHandler.Readable()then
    begin
            CommBlock := AThread.Connection.ReadLn();
    end
    else
    begin
            application.ProcessMessages;
    end;
until commblock <> '';

В любом случаеключевая строка - Application.ProcessMessages, так как это позволяет основному потоку проверять свои сообщения и продолжать работу.

0 голосов
/ 23 апреля 2010

Помните, что компоненты VCL не являются потокобезопасными, поэтому вы не можете получить к ним доступ напрямую из потока, иначе что-то пойдет не так, например, основной поток может застрять.

Поэтому убедитесь, что TMonitorFrm.ServerExecute не работаетчто-нибудь с формами и компонентами.Если вам нужно что-то обновить, используйте Синхронизировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...