根据LISTVIEW的内容实现多线程下载,我这样写行吗?为什么出错啊?
LISTVIEW的第一列是ID,第二列是文件名,第三列是URL
procedure tform1.DownloadProgress1(Sender: TDownLoadURL; Progress,
ProgressMax: Cardinal; StatusCode: TURLDownloadStatus;
StatusText: String; var Cancel: Boolean);
var
x:integer;
i,j:integer;
begin
if (progressmax<>0) and (progress<>0) then begin
x :=round((progress/progressMax)*100);
EnterCriticalSection(CriticalSection); for i:=0 to ListView1.Items.Count-1 do begin
if ListView1.Items[i].SubItems.Strings[1]=StatusText then
j:=i;
end;
ListView1.Items[j].SubItems.Strings[2]:=inttostr(x);
LeaveCriticalSection(CriticalSection);
end;
end;procedure tform1.down1(id:pchar);
var
DownLoadURL : TDownLoadURL;
begin
DownLoadURL := TDownLoadURL.Create(self);
EnterCriticalSection(CriticalSection);
with DownLoadURL do
begin
FileName := 'c:\p.rar'+id;
URL := ListView1.Items[strtoint(id)-1].SubItems.Strings[1];
OnDownloadProgress := DownloadProgress1;
end;
LeaveCriticalSection(CriticalSection);
DownLoadURL.ExecuteTarget(DownLoadURL);
end;procedure down2(id:pchar);
begin
form1.down1(id);
end;procedure TForm1.Button3Click(Sender: TObject);
var
ThreadID: THandle;
id:string;
i:integer;
begin
InitializeCriticalSection(CriticalSection);
for i:=1 to ListView1.Items.Count do begin
CreateThread(nil, 0, @down2, strnew(pchar(inttostr(i))), 0, ThreadID) ;
end;
LISTVIEW的第一列是ID,第二列是文件名,第三列是URL
procedure tform1.DownloadProgress1(Sender: TDownLoadURL; Progress,
ProgressMax: Cardinal; StatusCode: TURLDownloadStatus;
StatusText: String; var Cancel: Boolean);
var
x:integer;
i,j:integer;
begin
if (progressmax<>0) and (progress<>0) then begin
x :=round((progress/progressMax)*100);
EnterCriticalSection(CriticalSection); for i:=0 to ListView1.Items.Count-1 do begin
if ListView1.Items[i].SubItems.Strings[1]=StatusText then
j:=i;
end;
ListView1.Items[j].SubItems.Strings[2]:=inttostr(x);
LeaveCriticalSection(CriticalSection);
end;
end;procedure tform1.down1(id:pchar);
var
DownLoadURL : TDownLoadURL;
begin
DownLoadURL := TDownLoadURL.Create(self);
EnterCriticalSection(CriticalSection);
with DownLoadURL do
begin
FileName := 'c:\p.rar'+id;
URL := ListView1.Items[strtoint(id)-1].SubItems.Strings[1];
OnDownloadProgress := DownloadProgress1;
end;
LeaveCriticalSection(CriticalSection);
DownLoadURL.ExecuteTarget(DownLoadURL);
end;procedure down2(id:pchar);
begin
form1.down1(id);
end;procedure TForm1.Button3Click(Sender: TObject);
var
ThreadID: THandle;
id:string;
i:integer;
begin
InitializeCriticalSection(CriticalSection);
for i:=1 to ListView1.Items.Count do begin
CreateThread(nil, 0, @down2, strnew(pchar(inttostr(i))), 0, ThreadID) ;
end;
只能又添了个全局的函数down2(id:pchar)
调用 tform1.down1(id:pchar)
然后在createthread中再调用down2,这样写对吗?
begin
form1.down1(id);
end;
在执行Down函数时就并变串行了,即使并行的线程也要等待一个线程执行完down后方可执行!
个人认为应该这样:
每一个线程指定自己的工作范围
即线程1负责处理Listview中的1-4条URL
线程2负责处理Listview中的5-8条URL
这样就不用为Listview加锁了!也就避免了并变串的转换!
DownLoadURL := TDownLoadURL.Create(form1); 或 TDownLoadURL.Create(nil);
EnterCriticalSection(CriticalSection);
with DownLoadURL do
begin
FileName := 'c:\p.rar'+id;
URL := form1.ListView1.Items[strtoint(id)-1].SubItems.Strings[1];
OnDownloadProgress := form1.DownloadProgress1;
end;
LeaveCriticalSection(CriticalSection);
DownLoadURL.ExecuteTarget(DownLoadURL);但是在 OnDownloadProgess 中要操作主线程中的界面控件,就需要用 Synchronize 来执行了。
procedure tform1.DownloadProgress1(Sender: TDownLoadURL; Progress,
ProgressMax: Cardinal; StatusCode: TURLDownloadStatus;
StatusText: String; var Cancel: Boolean);
begin
Synchronize(process)
end;
procedure process();
var
x:integer;
i,j:integer;
begin
if (progressmax <>0) and (progress <>0) then begin
x :=round((progress/progressMax)*100);
EnterCriticalSection(CriticalSection); for i:=0 to form1.ListView1.Items.Count-1 do begin
if form1.ListView1.Items[i].SubItems.Strings[1]=StatusText then
j:=i;
end;
form1.ListView1.Items[j].SubItems.Strings[2]:=inttostr(x);
LeaveCriticalSection(CriticalSection);
end;
end;