Delphi simple TCP server hangs. The form is frozen, but the server continues to manage clients

I am using a form with IdTCPServer which manages lines from the client using the AThread.connection.readln / writeln system. Row processing works and it is not a problem.

The thing is, the form with the server on it hangs and doesn't load, but it still manages all the clients connected to it, so it works, but it just doesn't work like a form. I'll make the assumption that its sitting on a readline or whatever ... but I have no idea how I can fix this at this point in time.

Please, help.

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;

      

+2


a source to share


4 answers


Here's how to stop Readln by making it freeze. You need to check if there is something there to read. There are several ways to do this, you can make readln timeout

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

      

Or you can check if the connection is readable before reading the text.



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

      

The key line is Application.ProcessMessages anyway, as this allows the main thread to check its messages and keep running.

0


a source


Indy uses blocking sockets. He needs to hang the current thread. To use Indy components in a VCL thread while maintaining VCL responsiveness, add the component TIdAntifreeze

to the form. Indy components are aware of this component and periodically monitor it so that the VCL thread can continue processing messages.



+6


a source


If you think you cannot reliably track execution with the debugger, you can add explicit tracing information to your code .
Use OutputDebugString

to log information to either the IDE's EventLog when run from the IDE, or the DbgView (from SysInternals) when working outside of Delphi.

+4


a source


Remember that VCL components are not thread-safe, so you cannot access them directly from a thread, otherwise something will go wrong, for example, the main thread may get stuck.

So check that TMonitorFrm.ServerExecute does nothing with forms and components. If you need to update something, use Synchronize.

0


a source







All Articles