Newsgroups : Borland : borland.public.delphi.internet.winsock : 2007 Apr : Client in TThreadList/TList - Disappearing!!!!
| Subject: | Client in TThreadList/TList - Disappearing!!!! |
| Posted by: | "Jamie Dale" (jamie.da..@yahoo.com) |
| Date: | Mon, 23 Apr 2007 14:17:08 |
Hi all!
I have a rather annoying problem. I am using Client objects for my TCP
server which is using Indy v8.
This is the code which is causing me considerable problems...:
For info..
Server: TDataModule;
//Data.pas
Procedure WriteUsers;
var
List: TList;
AppPath: String;
I: Integer;
ini: TIniFile;
Client: Server_Main_Source.TUser;
begin
AppPath := ExtractFilePath(ParamStr(0));
If FileExists(AppPath + 'Data.ini') then
begin
List := Server.Users.LockList; //Users: TThreadList holding all client
objects
ini := TIniFile.Create(AppPath + 'Data.ini');
ini.WriteInteger('General', 'UserCount', 0);
ini.EraseSection('Users');
For I := 0 to List.Count -1 do
begin
Client := List[I]; // <<=== Client becomes 'Inaccessible due to
optimization'
WriteUser(Client.UserName, Client.Password, Client.Email); //Data.pas
<== Nothing is passed
end;
Server.Users.UnlockList;
end;
end;
My TUser is defined as:
type
TUser = class(TObject)
UserName,
Password,
Email,
Session,
Key,
IP: String;
Online,
Registered: Boolean;
Thread: TIdPeerThread;
Lock: TCriticalSection;
Permissions: Array of TPermissions;
constructor Create;
destructor Destroy; override;
end;
What makes matters worse is that the client only becomes inaccessible if the
client has logged on/disconnected. If they have not, then the client is
accessible and the variables can be seen by the debugger.
Here is the main code that handles the client logon:
//If Part1 is logon
If Part1 = 'LOGON' then
begin
//Remove current 1st part
Command := ParseRemove('¦', Command, 1); //Utils.pas
//Get 1st part
Part1 := Parse('¦', Command, 1);
//If login credentials are correct
If Check.ID(Part1, Parse('¦', Command, 2)) then //Check.pas
begin
//Write success message to client
Server.WriteMessage('security¦logon¦success', AThread);
//Get Client object
Client := TUser(AThread.Data); //Temporary client from OnConnect event
//Obtain list of clients from Users ThreadList
List := Server.Users.LockList;
Server.Users.UnlockList;
//Loop through Client List
For I := 0 to List.Count -1 do
begin
//If Listed Client User matches the user logging in
If UpperCase(TUser(List[I]).UserName) = UpperCase(Part1) then
begin
//Get 2nd Client object from List
Client2 := List[I]; //Client which was read from .ini file on
startup
Server.Users.Remove(Client2);
//Generate a sessionID
Client2.Session := Utils.GenerateString(0); //Utils.pas
//Set Key to empty string
Client2.Key := '';
//Set IP to that of temporary Client object
Client2.IP := Client.IP;
//Set Client to Online
Client2.Online := True;
//Set main-Client Thread to that of temporary Client object
Client2.Thread := Client.Thread;
//Remove temporary Client object from Users ThreadList
Server.Users.Remove(Client);
//Free the temporary Client
Client.Free;
//Store pointer to proper Client in thread data
AThread.Data := Pointer(Client2);
Server.Users.Add(Client2);
Break;
end;
end;
end
else
begin
//Write failure message to client
Server.WriteMessage('security¦logon¦failure', AThread);
end;
end;
When the program is started, the clients are read from a .ini file (I know
it's not ideal, but that is not my main issue here).
Can anyone see a problem here? - I've been up until 1:50am last night trying
to debug this, but the main problem is that the debugger will not let me see
the contents of List - IE you can't see each individual Client object.
Please help!