Reputation: 1706
i managed to fix some errors with disconnecting, now whenever a file is transferring the CPU Usage becomes 100%, i dunno what im doing wrong :S.....
const
MaxBufferSize = 1024;
type
TClient = class(TObject)
public
AContext: TIdContext;
FileSize: Integer;
Canceled: Boolean;
Transfered: Integer;
procedure ReceiveData;
procedure Update;
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
Data: string;
Client: TClient;
Item: TListItem;
begin
Data := AContext.Connection.IOHandler.ReadLn;
//Data := 'SEND|785548' = Command + | + FileSize
if Copy(Data, 1, 4) = 'SEND' then
begin
Delete(Data, 1, 5);
Client := TClient.Create;
Client.FileSize := StrToInt(Data);
Client.AContext := AContext;
Item := ListView1.Items.Add;
Item.Caption := AContext.Connection.Socket.Binding.PeerIP;
Item.Data := Client;
Client.ReceiveData;
end;
end;
procedure TClient.ReceiveData;
var
currRead : Integer;
FS: TFileStream;
begin
Canceled := False;
FS := TFileStream.Create('C:\Test.dat', fmCreate or fmOpenReadWrite);
FS.Size := 0;
Transfered := 0;
try
while (FS.Position < FileSize) and (Athread.Connection.Connected) and (not Canceled) do
begin
Application.ProcessMessages;
if (FileSize - FS.Position) >= MaxBufferSize then currRead := MaxBufferSize
else currRead := (FileSize - FS.Position);
AThread.Connection.IOHandler.ReadStream(FS, CurrRead);
Transfered := FS.Position;
Notify.NotifyMethod(Update);
Application.ProcessMessages;
end;
finally
FS.Free;
AThread.Connection.IOHandler.InputBuffer.Clear;
AThread.Connection.Disconnect;
AThread.RemoveFromList;
Notify.NotifyMethod(Update);
Application.ProcessMessages;
end;
end;
procedure TClient.Update;
begin
//Code to Display Progress bar and stuff (Simplified for now)
Form1.Label1.Caption := 'Transfered Data : ' + IntToStr(Transfered);
end;
Upvotes: 3
Views: 1427
Reputation: 597941
You and I covered this topic in the Embarcadero forums (cached on CodeNewsFast).
Upvotes: 1
Reputation: 15334
You're calling Application.ProcessMessages in your receive loop, presumably to keep the rest of your application from appearing to be frozen. The 100% CPU usage is a side effect.
You're better off using an IdAntiFreeze component (still kind of a hack) or putting the ReceiveData functionality in a thread.
Update:
Whoops. At first glance, I thought this was a client side transfer running in the main thread, but it's actually being called in a separate IdTcpServer thread. In this case, APZ28's advice is correct; don't call Application.ProcessMessages in a thread.
Upvotes: 4
Reputation: 43053
I dont' know anything about Indy (I use my own unit, which is lighter/faster than Indy, for all TCP/IP client/server stuff - see http://synopse.info), but I guess your IdTCPServer1Execute method should run in a background thread, which is not the case here.
So :
Upvotes: 2
Reputation: 1007
Get rid of Application.ProcessMessages; it MUST NOT be called under thread other than main one
Upvotes: 6
Reputation: 15438
Your looping constantly, an easy hack is to add an Sleep(1)
after your Application.ProcessMessages
.
But perhaps you could reorder your code to block on the ReadStream function, and only run when a reasonable amount of data is received, or a timeout has passed.
Upvotes: 1