delphi 协程应用之【协程批量并行下载组件】,200行代码实现 迅雷 的效果

下载的问题

我们在开发中,经常要下载一些东西,比如软件的升级包、或模块 bpl、或在线升级等;然后 delphi 官方没有提供下载组件,若开发者自己开发 下载组件,估计很多开发者目前都是使用 主线程 + httpclient 来进行单线程下载,效率低下;原因如下:

  1. I/O(输入/输出)操作的阻塞性:

    • 单线程下载:在单线程中,当进行I/O操作时(如网络数据的读取),CPU会等待该操作完成才能继续执行后续任务。这会导致CPU在等待I/O完成时处于空闲状态,利用率低下。
  2. 网络带宽的利用率:

    • 单线程下载:单线程下载时,网络带宽的利用率往往无法达到最佳状态,因为单个线程无法充分利用网络带宽的波动和冗余。
  3. TCP流量控制的影响:

    • 单线程下载:传统的TCP流量探测机制存在缺陷,一旦检测到丢包,会立即将发送速率降为一半。这会导致下载速率波动较大,难以持续保持高速。
  4. 硬件和资源的限制:

    • 单线程下载:单线程下载受到CPU、内存等硬件资源的限制较小,但无法充分利用网络带宽。

结论

在网速固定的情况下,单线程下载效率很低,线程数也不是越多越好,多线程下载组件,也是难以开发的,还有线程中途取消的问题,我估计 很多厉害的人,也难以开发 像 迅雷这种 下载组件,多线程 分片下载,内存流 顺序合并,还有UI 轮播展示内部信息的问题;

协程下载组件 djDownloader

用协程实现这个 下载组件,只需要 200行代码,实现 迅雷的 分片下载,内存流 顺序合并,并行下载,把您的网速打满,与迅雷的下载 旗鼓相当,多个URL 批量并行下载,显示速率、剩余时间、轮询播放每个URL的进度;

示例代码

procedure TFormMain.Button1Click(Sender: TObject);
begin
  button1.Enabled := False;
  //搜狗浏览器 82.23MB
  djDownloader1.addUrl('https://dlie.sogoucdn.com/se/sogou_explorer_11.0.1.34700_0000.exe', 'C:\测试下载');
  //QQ音乐 69.86MB 这种带参数的也是没有问题的
  djDownloader1.addUrl('https://dldir1v6.qq.com/music/clntupate/QQMusic_Setup_2111.exe?aa=xxx&bb=xxx', 'C:\测试下载');
  //迅雷 7.90MB,不满一个分片
  djDownloader1.addUrl('https://down.sandai.net/thunder11/XunLeiWebSetup12.1.2.2662xl11.exe', 'C:\测试下载');
  //360压缩 14.98MB,可以指定不同的文件夹
  djDownloader1.addUrl('https://sfdl.360safe.com/360zip_setup.exe', 'C:\新文件夹');
  djDownloader1.start; //批量并行下载
end;

批量下载4个文件,并保存到不同的文件夹下,批量并行下载,支持下载过程中取消;

示例效果

image

其它配置

image

image

完整代码

unit main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, ddj.Downloader;

type
  TFormMain = class(TForm)
    Button1: TButton;
    djDownloader1: TdjDownloader;
    procedure Button1Click(Sender: TObject);
    procedure djDownloader1Canceled(Sender: TObject);
    procedure djDownloader1Completed(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormMain: TFormMain;

implementation

{$R *.dfm}

procedure TFormMain.Button1Click(Sender: TObject);
begin
  button1.Enabled := False;
  //搜狗浏览器 82.23MB
  djDownloader1.addUrl('https://dlie.sogoucdn.com/se/sogou_explorer_11.0.1.34700_0000.exe', 'C:\测试下载');
  //QQ音乐 69.86MB 这种带参数的也是没有问题的
  djDownloader1.addUrl('https://dldir1v6.qq.com/music/clntupate/QQMusic_Setup_2111.exe?aa=xxx&bb=xxx', 'C:\测试下载');
  //迅雷 7.90MB,不满一个分片
  djDownloader1.addUrl('https://down.sandai.net/thunder11/XunLeiWebSetup12.1.2.2662xl11.exe', 'C:\测试下载');
  //360压缩 14.98MB,可以为每个URL指定不同的文件夹
  djDownloader1.addUrl('https://sfdl.360safe.com/360zip_setup.exe', 'C:\测试下载');
  djDownloader1.start; //批量并行下载
end;

procedure TFormMain.djDownloader1Canceled(Sender: TObject);
begin
  ShowMessage('已取消成功!');
  button1.Enabled := True;
end;

procedure TFormMain.djDownloader1Completed(Sender: TObject);
begin
  ShowMessage('已全部下载成功!');
  button1.Enabled := True;
end;

end.
posted @ 2025-02-25 16:37  殴阳疯  阅读(129)  评论(0)    收藏  举报