一、项目需求
   建立多个线程,同时对多个不同的下载任务进行下载二、我目前的代码示例
unit main;interfaceuses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, ComCtrls, ExtCtrls, StdCtrls, Spin, IdBaseComponent, IdComponent,
   IdTCPConnection, IdTCPClient, IdHTTP, IdAntiFreezeBase, IdAntiFreeze;type
   TWeiBoThread=class(TThread)
   private
   // IdHttp_Sina:TIdHTTP;
   fs:TStringStream;
   UpdateFuncID:integer;
   IsFinished:Bool;
   // FURL:string ;
   public
   sURL,sFileSave:string;
   ThreadSumCount:integer;
   ThreadIndex:integer; //当前线程编号
   WhatLV:TListView;// IsBusy:Bool; //是否正在忙
//
// // IsPause_WaitDial:Bool; //主线程是否发货了暂停的命令,如果是,要挂起线程
//
// RoundIndex:integer;
   LVIndex, WebIndex:integer;   constructor Create( CreateSuspended: Boolean);
   destructor Destroy; override;
   procedure Execute ; override;
   procedure SendID(nID:string);
   procedure ThreadDone( );   procedure UpdateListView();
   end;
type
   TfmMain = class(TForm)
   Panel1: TPanel;
   Panel2: TPanel;
   edtThreadCount: TSpinEdit;
   Label2: TLabel;
   btnInit: TButton;
   Button1: TButton;
   IdHTTP1: TIdHTTP;
   IdAntiFreeze1: TIdAntiFreeze;
   Button2: TButton;
   Button3: TButton;
   Button4: TButton;
   PageControl1: TPageControl;
   TabSheet1: TTabSheet;
   TabSheet2: TTabSheet;
   lvUserList: TListView;
   mmLog: TMemo;
   procedure btnInitClick(Sender: TObject);
   procedure Button1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure Button3Click(Sender: TObject);
   procedure Button4Click(Sender: TObject);
   private
   { Private declarations }
   public
   { Public declarations }
   TaskSumNum,FinishedTask:Integer;
   end;var
   fmMain: TfmMain;   MyThreadList: array of TWeiBoThread;implementation{$R *.dfm}{ TWeiBoThread }constructor TWeiBoThread.Create (CreateSuspended: Boolean);
begin
   inherited Create(false);   LVIndex:=0;
end;destructor TWeiBoThread.Destroy;
begin
   Terminate; //TY   inherited;
end;procedure TWeiBoThread.Execute;
var
   idHttp_Sina: TIdHttp;   myStream:TStringStream;
begin
   //用此句在运行过程中就报错,未知原因。2011-8-16 //●●●问题点4
   //FreeOnTerminate := True; {这可以让线程执行完毕后随即释放}   if IsFinished then Exit;
   myStream:= TStringStream.Create;   UpdateFuncID:=1; //1表示显示开始时间
   Synchronize( UpdateListView );
   //WhatLV.Items[LVIndex].SubItems[1]:= '开始:' + FormatDateTime('hh:mm:ss',now ) ;
   idHttp_Sina:= TIdHttp.Create(nil);        idHttp_Sina.Get('http://www.163.com?' + IntToStr(LVIndex) , myStream );
   //idHttp_Sina.Get('http://www.baidu.com?' + IntToStr(LVIndex) , myStream );   //华军软件园,不同的网页
   // idHttp_Sina.Get('http://www.onlinedown.net/soft/' + IntToStr( 44800 + LVIndex) + '.htm' , myStream );   UpdateFuncID:=2; //1表示显示开始时间
   Synchronize( UpdateListView );
   myStream.SaveToFile( 'OutFile\' +
   IntToStr(LVIndex) + '@' + FormatDateTime('hhmmss',now ) + '.txt'
   ) ;   myStream.Free;
   idHttp_Sina.Free;   Sleep(100);   IsFinished:=True;   inc( fmMain.FinishedTask );   if fmMain.FinishedTask = fmMain.TaskSumNum then
   begin   fmMain.mmLog.Lines.Add('多线程完成时间:' + FormatDateTime('hh:mm:ss',now ) );
   ShowMessage('所有任务都已完成!');
   end;
   inherited;
end;procedure TWeiBoThread.SendID(nID: string);
begin
   //
end;procedure TWeiBoThread.ThreadDone;
begin
exit;   WhatLV.Items[LVIndex].SubItems[1]:=
   WhatLV.Items[LVIndex].SubItems[1] + '...ThreadDone:完成:' + FormatDateTime('hh:mm:ss',now ) ;
end;
procedure TWeiBoThread.UpdateListView;
begin
   if UpdateFuncID=1 then
   WhatLV.Items[LVIndex].SubItems[1]:= inttostr(LVIndex) + ' 开始:' + FormatDateTime('hh:mm:ss',now )
   else if UpdateFuncID=2 then
   begin
   WhatLV.Items[LVIndex].SubItems[1]:=
   WhatLV.Items[LVIndex].SubItems[1] + '...完成:' + FormatDateTime('hh:mm:ss',now ) ;
   end;
//Synchronize()的作用? 多线程之间控制同步过程.比方说要访问一种资源时,避免同时操作.//synchronize是不可以带参数的。
end;//////////////////////procedure TfmMain.Button1Click(Sender: TObject); //建立线程
var
   i:integer;
begin
   Caption:= '多线程...';   TaskSumNum:= edtThreadCount.Value;
   FinishedTask:=0;   SetLength(MyThreadList, edtThreadCount.Value +1 ); //线程数量
   mmLog.Lines.Add('多线程开始时间:' + FormatDateTime('hh:mm:ss',now ) );   for I := 1 to edtThreadCount.Value do
   begin
   MyThreadList[i] := TWeiBoThread.Create( false );
   MyThreadList[i].LVIndex:= i-1;
   MyThreadList[i].WhatLV:= lvUserList;   // MyThreadList[i].FreeOnTerminate:=True;
   // MyThreadList[i].OnTerminate:= MyThreadList[i].ThreadDone; //
   end;   for I := 1 to edtThreadCount.Value do
   begin
   //MyThreadList[i].Resume;
   // MyThreadList[i].Start;
   MyThreadList[i].Execute;
   end;   mmLog.Lines.Add('多线程呼叫完成,等待线程们处理,呼叫时间:' + FormatDateTime('hh:mm:ss',now ) );end;
  
procedure TfmMain.Button3Click(Sender: TObject); //挂起线程 //●●●问题点3
var
   i:integer;
begin
   for I := 1 to edtThreadCount.Value do
   begin
// MyThreadList[i].Suspend;
   if MyThreadList[i].Terminated=False then
   MyThreadList[i].Suspended:= True;   end;
end;procedure TfmMain.Button4Click(Sender: TObject); //继续线程
var
   i:integer;
begin
   for I := 1 to edtThreadCount.Value do
   begin
   MyThreadList[i].Resume; // .Suspend; //如果线程已终止,则无法暂停止
   end;
end;procedure TfmMain.FormCreate(Sender: TObject);
begin
   btnInit.Click;
end;procedure TfmMain.btnInitClick(Sender: TObject);
var
   nIndex,i:integer;
begin
   lvUserList.Items.Clear;
   nIndex:=0;
   for i := 0 to 1000 - 1 do
   begin //产生1000个数字序列   inc(nIndex);
   with lvUserList.Items.Add do
   begin
   Caption:= inttostr(nIndex);
   SubItems.Add( 'Num' + inttostr(nIndex) ) ;   SubItems.Add( '' ) ;   end;
   end;
end;
end.------------------------三、问题点
1、上述代码,为什么我的线程任务全部完成后,在ListView中,开头的1-2个任务还会重新执行一次?
2、假设我现在有1000个任务要下载,然后我建立了10个线程,是不是就是在 Execute 中,放一个For 循环,如下:
procedure TWeiBoThread.Execute;
....
Begin
   For i:=1 to 任务总数 / 线程数 + 1
   Begin
   if i >= WhatLV.Items.Count then Exit;   //这里面写原来的那些Execute语句体
   End
End;
是这样重复去下载吗?3、问题3
   以问题2为例,我现在假设下载完成 XX 个任务时,要重新拨号,那么,我要怎么挂起任务,然后等拨号成功后再继续执行?
   我现在的方法是想在主程序中先检测是否需要重新拨号,如果是,就执行上面的 //●●●问题点3   
   3.1 但我发现假如某个线程正在执行中,它好像根本不暂停或挂起。
   3.2 如果说是一个线程必须要execute完毕才能挂起,那我拨号完后,怎么让它从下一个循环继续开始?是自己去控制 For 语句的开始数值,还是线程有其它方法让程序继续?   3.3 我们挂起一个线程,再继续一个线程时,它是重新执行 Execute ,还是从原来线程没有完成的地方继续执行?
   3.4 在线程们执行过程中,我要强行退出程序,又要怎么做?我发现好像程序都关闭i不了,非得全部执行完。
4、问题点4
     
   //用此句在运行过程中就报错,未知原因。2011-8-16 //●●●问题点4
   //FreeOnTerminate := True; {这可以让线程执行完毕后随即释放}   上述一行代码,我为什么一加上它,程序运行就会报内存错?
以上诸个问题,诚请过来人和大虾们指教!
谢谢!

解决方案 »

  1.   

    针对4,个人不建议FreeOnTerminate := True;手动释放更方便。
      

  2.   

    代码太多,不细看了,直接回复你的相关问题!1.对于这个问题,应该是你没有加入同步开始数值的问题。每次开始都是从起初开始执行的!
    2.使用while not terminated do这样的去判断是否终止吧,里边加入你想跳出循环的一个判断语句
    3.1应该是你的代码有问题吧,应该可以挂起的。
    3.2拨号完后直接使用唤醒就行了
    3.3从原来线程没有完成的地方执行
    3.4如果是线程的话,怎么会关闭不了呢?是不是线程没有用对?关闭线程可以使用TThread.Terminate;然后TThread.Free;释放线程。
    4.如果使用Freeonterminate的话就不要使用TThread.Free这样的了,会提示访问句柄错误的。
    如果在线程执行的时候想关闭程序,就先判断一下线程是否正在运行,如果正在运行则TThread.Terminate,然后再TThread.Free;