在用HttpCli进行多线程下载时,遇到我解决了半天也没解决的问题,请大虾指教。(300分)

章慧

Unregistered / Unconfirmed
GUEST, unregistred user!
1。仿照范例CreateThread时,True ->suspend
可是。用Resume执行线程发现For了一群线程,只有第一个在跑,其他的都若无其事。
用Execute执行,可以,但是总下载不正确。大约48?k之后开始面目全非。
2。为此多线程建立界面,所有的线程都create(true),execute,边下边显示,发现
只有第一个线程下完了,第二个线程才开动。不知道为什么?请指教。
相关程序如下:
1。线程文件
Unitdo
wnloadThread;
Interface
Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
HttpProt;
Const
tnFree = 0;
tnDownloadbegin
= 1;
tnDownloading = 2;
tnDownloadEnd = 3;
tnDownloadFailed= 4;
tnAbort = 5;
Type
TDownloadThread = Class(TThread)
Private
ThreadNotice: Integer;
do
wnloadFile: TFileStream;
Proceduredo
cbegin
(Sender : TObject);
Proceduredo
cData(Sender : TObject;
Buffer : Pointer;
Len : Integer);
Proceduredo
cEnd(Sender : TObject);
Procedure NoticeIt;
Procedure NoticeMe;
Published
Procedure Execute;
Override;
Public
FLen : Integer;
FURL : String;
FProxy : String;
FPort : Integer;
FThreadNo : Integer;
FHttpCli : THTTPCli;
FStartPos : Integer;
FEndPos : Integer;
FDownloadto : String;
end;
Implementation
Uses
Process;
Procedure TDownloadThread.NoticeIt;
begin
MainWindow.ThreadNotice(ThreadNotice,FThreadNo,0);
end;
Procedure TDownloadThread.NoticeMe;
begin
MainWindow.ThreadNotice(ThreadNotice,FThreadNo,FLen);
end;
Procedure TDownloadThread.Execute;
begin
FreeOnTerminate:=True;
ThreadNotice:=tnFree;
Try
do
wnloadFile:=TFileStream.Create(FDownloadto,fmOpenReadWrite,fmShareDenyNone);
Except
end;
FHttpCli := THTTPCli.Create(Nil);
FHttpCli.MultiThreaded := TRUE;
FHttpCli.RcvdStream := TMemoryStream.Create;
FHttpCli.OnDocbegin
:=do
cbegin
;
FHttpCli.OnDocEnd :=do
cend;
FHttpCli.OnDocData :=do
cData;
With FHttpClido
begin
URL := FURL;
If FProxy='' then
begin
Proxy:='';
ProxyPort:='';
End
else
begin
Proxy := FProxy;
ProxyPort:=IntToStr(FPort);
end;
ContentRangebegin
:=IntToStr(FStartPos);
ContentRangeEnd:=IntToStr(FEndPos);
do
wnloadFile.Seek(FStartPos,soFrombegin
ning);
(RcvdStream As TMemoryStream).Clear;
Try
ThreadNotice:=tnDownloading;
Get;
Except
begin
ThreadNotice:=tnDownloadFailed;
Synchronize(NoticeIt);
end;
end;
If FHttpCli.RcvdStream<>Nil then
FHttpCli.RcvdStream.Free;
FHttpCli.Free;
ThreadNotice:=tnFree;
Synchronize(NoticeIt);
end;
end;
Procedure TDownloadThread.Docbegin
(Sender : TObject);
begin
ThreadNotice:=tnDownloadbegin
;
Synchronize(NoticeIt);
end;
Procedure TDownloadThread.DocData(Sender : TObject;
Buffer : Pointer;
Len : Integer);
Var
i:Integer;
begin
ThreadNotice:=tnDownloading;
If FStartPos+Len>FEndPos+1 then
i:=FEndPos+1-FStartPos else
i:=Len;
FLen:=i;
do
wnloadFile.WriteBuffer(Buffer^,i);
FStartPos:=DownloadFile.Seek(0,soFromCurrent);
Synchronize(NoticeMe);
end;
Procedure TDownloadThread.DocEnd(Sender : TObject);
begin
ThreadNotice:=tnDownloadend;
do
wnloadFile.Free;
Synchronize(NoticeIt);
end;
end.
2。主文件 的 一部分
Unit Process;
....
Function TMainWindow.RunThreads(TaskNumber,ThreadNumber:Integer):Integer;
Var
i:Integer;
begin
i:=GetFreeThread;
Result:=i;
If i>0 then
begin
Inc(ThreadQuantity);
ThreadDataIndex[TaskNumber,i]:=ThreadNumber;
ThreadData.TaskNo:=TaskNumber;
ThreadData.Status:=tsWorking;
ThreadData.StartPos:=FileDataBase[TaskNumber].UnDownloadedContent[ThreadNumber].StartPos;
ThreadData.EndPos:=FileDataBase[TaskNumber].UnDownloadedContent[ThreadNumber].EndPos;
Threads:=TDownloadThread.Create(True);
Threads.FURL:=FileDataBase[TaskNumber].URL;
Threads.FProxy:=FileDataBase[TaskNumber].Proxy;
If FileDataBase[TaskNumber].Proxy='' then
Threads.FPort:=0
else
Threads.FPort:=StrToInt(FileDataBase[TaskNumber].Port);
Threads.FThreadNo:=i;
Threads.FStartPos:=ThreadData.StartPos;
Threads.FEndPos:=ThreadData.EndPos;
Threads.FDownloadto:=FileDataBase[TaskNumber].Downloadto;
Threads.Execute;
end;
end;
Procedure TMainWindow.AddSingleTask(URL,do
wnloadto, Proxy:String;Port,ThreadsNumber,TaskNumber:Integer);
Var
i,j,k:Integer;
begin
j:=TestURL(URL,Proxy,Port);
If TaskNumber=0 then
begin
Inc(FileDataQuantity);
TaskNumber:=FileDataQuantity;
FileDataBase[TaskNumber].URL:=URL;
FileDataBase[TaskNumber].Downloadto:=Downloadto;
FileDataBase[TaskNumber].Proxy:=Proxy;
If Proxy='' then
FileDataBase[TaskNumber].Port:=''
else
FileDataBase[TaskNumber].Port:=IntToStr(Port);
FileDataBase[TaskNumber].ThreadNo:=ThreadsNumber;
FileDataBase[TaskNumber].Status:=fsWaiting;
FileDataBase[TaskNumber].RequestTime:=DateTimeToStr(Date);
FileDataBase[TaskNumber].ErrorInfo:='';
FileDataBase[TaskNumber].Error:=0;
FileDataBase[TaskNumber].Lenth:=j;
For i:= 0 to 49do
begin
FileDataBase[TaskNumber].ThreadRunning:=False;
FileDataBase[TaskNumber].UnDownloadedContent.StartPos:=0;
FileDataBase[TaskNumber].UnDownloadedContent.EndPos:=0;
end;
For i:=0 to 400do
ThreadDataIndex[TaskNumber,i]:=0;
If j>0 then
If ThreadQuantity<400 then
begin
k:=ThreadsNumber;
If (k+ThreadQuantity)>400 then
k:=400-ThreadQuantity;
DecideTask(TaskNumber,j,k);
If CreatePsychopath(Downloadto,j) then
begin
For i:=1 to kdo
begin
FileDataBase[TaskNumber].ThreadRunning[i-1]:=True;
RunThreads(TaskNumber, i-1);
end;
End
else
begin
FileDataBase[TaskNumber].Status:=fsDeleted;
FileDataBase[TaskNumber].Error:=FileDataBase[TaskNumber].Error+1;
FileDataBase[TaskNumber].ErrorInfo:=Downloadto+' can not be created.';
FillFileData(ActivePages);
end;
End
else
begin
FileDataBase[TaskNumber].Status:=fsWaiting;
FileDataBase[TaskNumber].Error:=FileDataBase[TaskNumber].Error+1;
FileDataBase[TaskNumber].ErrorInfo:='Not enough thread resource.';
FillFileData(ActivePages);
End
else
begin
DisplayMessage('The URL: '+URL+' cannot bedo
wnloaded any more, auto dropped this task to rubbish box.');
FileDataBase[TaskNumber].ErrorInfo:='Cannot connect, File not exists, or length is zero.';
FileDataBase[TaskNumber].Error:=FileDataBase[TaskNumber].Error+1;
FileDataBase[TaskNumber].Status:=fsDeleted;
FillFileData(ActivePages);
end;
End
else
begin
FileDataBase[TaskNumber].Status:=fsWaiting;
FileDataBase[TaskNumber].RequestTime:=DateTimeToStr(Date);
If j>0 then
If ThreadQuantity<400 then
begin
k:=ThreadsNumber;
If (k+ThreadQuantity)>400 then
k:=400-ThreadQuantity;
If FileDataBase[TaskNumber].UnDownloadedContent[0].EndPos=0 then
DecideTask(TaskNumber,j,k);
If CreatePsychopath(Downloadto,j) then
begin
For i:=1 to kdo
begin
FileDataBase[TaskNumber].ThreadRunning[i-1]:=True;
RunThreads(TaskNumber, i-1);
end;
End
else
begin
FileDataBase[TaskNumber].Status:=fsDeleted;
FileDataBase[TaskNumber].Error:=FileDataBase[TaskNumber].Error+1;
FileDataBase[TaskNumber].ErrorInfo:=Downloadto+' can not be created.';
FillFileData(ActivePages);
end;
End
else
begin
FileDataBase[TaskNumber].Status:=fsWaiting;
FileDataBase[TaskNumber].Error:=FileDataBase[TaskNumber].Error+1;
FileDataBase[TaskNumber].ErrorInfo:='Not enough thread resource.';
FillFileData(ActivePages);
End
else
begin
DisplayMessage('The URL: '+URL+' cannot bedo
wnloaded any more, auto dropped this task to rubbish box.');
FileDataBase[TaskNumber].ErrorInfo:='Cannot connect, File not exists, or length is zero.';
FileDataBase[TaskNumber].Error:=FileDataBase[TaskNumber].Error+1;
FileDataBase[TaskNumber].Status:=fsDeleted;
FillFileData(ActivePages);
end;
end;
end;
Procedure TMainWindow.ThreadNotice(Notice, ThreadNumber, Info:Integer);
Var
i,j,k,l:Integer;
begin
l:=0;
i:=ThreadData[ThreadNumber].TaskNo;
j:=ThreadDataIndex[i,ThreadNumber];
//Memo1.Lines.Add(IntToStr(Notice)+','+IntToStr(i)+','+IntToStr(j)+','+IntToStr(ThreadNumber)+','+IntToStr(Info));
Case Notice Of
tnDownloadEnd:begin
l:=1;
k:=CheckTaskStatus(i);
//DisplayMessage(IntToStr(i)+','+IntToStr(j)+','+IntToStr(k));
If (k=ctsDownloaded) And (FileDataBase.Status=fsDownloading) then
begin
FileDataBase.Status:=fsDownloaded;
FillFileData(ActivePages);
end;
end;
tnDownloadFailed:begin
l:=2;
FileDataBase.Error:=FileDataBase.Error+1;
FileDataBase.ErrorInfo:='Thread reportdo
wnloading error: Connention refused.';
k:=CheckTaskStatus(i);
If (k=ctsWaitingDelete) And (FileDataBase.Status=fsDownloading) then
begin
FileDataBase.Status:=fsDeleted;
FillFileData(ActivePages);
end;
end;
tnDownloading:begin
FileDataBase.UnDownloadedContent[j].StartPos:=FileDataBase.UnDownloadedContent[j].StartPos+Info;
ThreadData[ThreadNumber].StartPos:=ThreadData[ThreadNumber].StartPos+Info;
end;
tnDownloadbegin
:begin
l:=3;
FileDataBase.Status:=fsDownloading;
end;
tnFree:begin
FileDataBase.ThreadRunning[j]:=False;
ThreadData[ThreadNumber].Status:=tsFree;
Dec(ThreadQuantity);
end;
end;
If (Time>Times+ShowTime[ThreadNumber]) Or (l>0) then
begin
DisplayInfoIfNeed(ThreadNumber);
ShowTime[ThreadNumber]:=Time;
end;
//DisplayInfoIfNeed(ThreadNumber);
end;

 
2. Threads.Execute;这句话不要出现在主程序里面,因为这意味着主线程要等待该线程
退出才继续下一语句。
Thread.Execute是自动的,Create之后就会自动运行,除非你用参数Create(true)
 
终于搞成了^O^
问题不在那里,我试过了,虽然调用Execute是不对的,但各线程都跑起来了。
我自己找到了问题所在,就是那个Try TFileStream.Create,死在Try上了
没Try的话立刻报错。
我建了一个主线程文件流,让他们写,就对了。
但是还是多谢多谢
 
但是有try的话,居然能等到上一个线程全写完,try到底在做什么啊?
 
顶部