我设法通过断开连接修复了一些错误,现在每当文件传输CPU使用率变为100%时,我不知道我做错了什么: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;
答案 0 :(得分:6)
摆脱Application.ProcessMessages;它绝不能在主线程之外的线程下调用
答案 1 :(得分:4)
您在接收循环中调用Application.ProcessMessages,可能是为了防止应用程序的其余部分被冻结。 100%的CPU使用率是副作用。
最好使用IdAntiFreeze组件(仍然是一种黑客攻击)或将ReceiveData功能放在一个线程中。
更新
糟糕。乍一看,我认为这是在主线程中运行的客户端传输,但它实际上是在一个单独的IdTcpServer线程中调用的。在这种情况下,APZ28的建议是正确的;不要在一个线程中调用Application.ProcessMessages。
答案 2 :(得分:2)
我对Indy一无所知(我使用自己的单位,比Indy更轻/更快,对于所有TCP / IP客户端/服务器的东西 - 请参阅http://synopse.info),但我想你的IdTCPServer1Execute方法应该在后台线程中运行,这不是这里的情况。
所以:
答案 3 :(得分:1)
您的循环不断,一个简单的黑客就是在Sleep(1)
之后添加Application.ProcessMessages
。
但也许您可以重新排序代码以阻止ReadStream函数,并且仅在收到合理数量的数据或超时时才运行。
答案 4 :(得分:1)
您和我在Embarcadero forums(cached on CodeNewsFast)中介绍了此主题。