多线程下载多个任务,分批下载,及相关问题的请教
建立多个线程,同时对多个不同的下载任务进行下载
二、我目前的代码示例
unit main;
interface
uses
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; {这可以让线程执行完毕后随即释放}
上述一行代码,我为什么一加上它,程序运行就会报内存错?
以上诸个问题,诚请过来人和大虾们指教!
谢谢!
相关推荐
Android高效多线程文件下载实现
本文还有配套的精品资源,点击获取 简介:本项目为Android平台上的"down_ANDROID",重点讲解如何使用Download Service在后台高效下载大文件,以及多线程技术加速下载过程。通过该示例项目,开发者可以了解如何创建自定义下载管理器,实现文件的下载、暂停、恢复和取消等操作。实现步骤包括初始化下载任务、设置请求头、创建多线程、下载部分文件、保存本地文件、合...
高校及科研院所如何利用外部数据完善技术转移转化机制.docx
科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。
完全复现虚拟同步发电机VSG自适应惯量阻尼控制仿真、根轨迹、调节系数对比(Simulink仿真、Matlab代码实现)
内容概要:本文档围绕“【完全复现】虚拟同步发电机VSG自适应惯量阻尼控制仿真、根轨迹、调节系数对比”这一主题,利用Simulink和Matlab平台,系统性地实现了虚拟同步发电机(VSG)的自适应惯量与阻尼控制策略的建模与仿真。内容涵盖VSG的核心控制原理、系统动态响应特性分析、根轨迹绘制以及在不同调节系数下的性能对比研究,旨在深入剖析关键控制参数对系统稳定性与动态性能的影响机制,为新能源并网系统中提升频率支撑能力和暂态稳定性的控制策略设计提供理论依据和技术支持。; 适合人群:具备扎实的电力系统分析与自动控制理论基础,熟练掌握Matlab/Simulink仿真工具,主要从事新能源发电、微电网运行、电力电子变换器控制或电力系统稳定研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①开展虚拟同步发电机(VSG)的建模与先进控制策略的深入研究;②探究自适应惯量与阻尼控制对改善电网频率响应速度和平抑功率波动的作用机理;③运用根轨迹法进行系统稳定性分析,并指导控制器参数的优化整定;④完成高水平学术论文撰写或科研项目申报所需的仿真复现实验。; 阅读建议:本资源以“完全复现”为核心目标,提供了完整的仿真模型与配套代码。使用者应在深入理解同步发电机转子运动方程、虚拟惯量及阻尼物理意义的基础上,结合电力系统暂态稳定理论,逐步操作并调试仿真模型,尤其需关注不同调节系数变化对系统动态性能指标(如超调量、调节时间)的影响,从而深化对VSG内在控制机制与稳定边界的认知。
前端开发基于history.js的HTML5与HTML4浏览器兼容方案:单页应用无刷新历史状态管理技术实现-dQ4ehf7C1792158475
内容概要:本文系统介绍了如何利用history.js实现单页应用(SPA)在HTML5c与HTML4浏览器间s草错发的无缝历史状态管理。通过封装原生History API并在不支持的浏览器中自动降级为哈希路由,history.js解决了因浏览器兼容性导致的后退按钮失效、URL混乱等问题。文章详细讲解了其核心机制,包括状态对象管理、自动模式切换(HTML5 pushState vs HTML4 哈希)、状态数据持久化以及针,对Safari、IE等浏\览器的兼容性修复方案,并提供了从入门到实战的完整示例,涵盖初始化、事,件监听、页面加载及性能优化技巧。;DtPXB1792158476
员工满意度数据集(11列,12000 条记录)CSV 合成
详情介绍:该 HR 员工数据集含 12,000 条 ×11 列(满意度、绩效评估、项目数、月均工时、司龄、工伤、福利包、晋升、部门、薪资),无缺失值但无离职标签列,且存在数据质量问题(141 条负绩效评估、144 条负工时、49.4% 异常高工伤率、项目数仅 0/1/2),疑似经过修改或合成,不能直接做经典的员工离职预测,适合做满意度回归、薪资三分类、晋升预测或员工聚类分析,使用前必须清洗异常值并注意数据真实性限制。


