前几天刚碰到过的问题,卡的原因是因为磁盘的频繁写入造成的。
解决方式就是 将接收到的数据写到一个队列
由另外一个线程判断队列内的数据超过多少或者传送完毕再写一次磁盘。
我这样写出来以后效果很不错 支持并发多任务,在局域网速度能到10M左右/s
无论同时多少个并发传输CUP使用率保持在20以下。
贴小段代码以做参考:)
=============
try
lUserbuff.ConnToFile(LOpter.FileName);
LRecBuff := GetMemory(1024 * 8);
LRecSize := Lbuff.EndPos - Lbuff.StartPos;
{总共要读取的大小}
LCurrRec := 0;
{已经读取的大小}
LTrueSize := Min(1024 * 8, LRecSize - LCurrRec);
while (LCurrRec < LRecSize) and (ClientThread.Socket.Connected)do
begin
LTrueSize := ClientThread.Socket.ReceiveBuf(LRecBuff^, LTrueSize);
lUserbuff.AddToQueue(LRecBuff, LTrueSize);
inc(LCurrRec, LTrueSize);
LTrueSize := Min(1024 * 8, LRecSize - LCurrRec);
{注意接收太快的时候必须限制速度否则写入磁盘的速度是没有接收速度快的内存很快就用光光了}
while lUserbuff.CurrBuffSize > CMissonRecBuffdo
sleep(10);
end;
// while
Shower.AddShow('LCurrRec : %d LRecSize:%d ClientThread.Socket.Connected:%s', [LCurrRec, LRecSize, BoolToStr(ClientThread.Socket.Connected)]);
if LCurrRec = LRecSize then
LOpter.FinishAnThread(Lbuff);
ClientThread.fpSessionData := nil;
{传输完成后 只释放连接 不释放对象因为也许还有数据未写入文件}
except
on e: Exceptiondo
Shower.AddShow('接收数据时异常原因 :%s 将结束此用户上传的所有相关线程', [e.Message]);
end;