如何取消 pause/resume Web 客户端异步下载?
How can I cancel and pause/resume web client download async?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using unfreez_wrapper;
namespace Downloads
{
public partial class Form1 : Form
{
List<string> urls = new List<string>();
DownloadProgressTracker tracker;
long myLong = 0;
WebClient client;
public Form1()
{
InitializeComponent();
tracker = new DownloadProgressTracker(50, TimeSpan.FromMilliseconds(500));
lblDownloadProgress.Text = "";
lblStatus.Text = "Download Pending";
lblAmount.Text = "";
lblSpeed.Text = "";
urls.Add("https://speed.hetzner.de/10GB.bin");
urls.Add("https://speed.hetzner.de/100MB.bin");
}
private async Task DownloadAsync()
{
using (var client = new WebClient())
{
this.client = client;
client.DownloadFileCompleted += (s, e) =>
{
if (e.Cancelled)
{
client.Dispose();
return;
}
};
client.DownloadFileCompleted += (s, e) => lblStatus.Text = "Download File Completed.";
client.DownloadProgressChanged += (s, e) => tracker.SetProgress(e.BytesReceived, e.TotalBytesToReceive);
client.DownloadProgressChanged += (s, e) => lblAmount.Text = SizeSuffix(e.BytesReceived) + "/" + SizeSuffix(e.TotalBytesToReceive);
client.DownloadProgressChanged += (s, e) => lblSpeed.Text = tracker.GetBytesPerSecondString();
client.DownloadProgressChanged += (s, e) => myLong = Convert.ToInt64(client.ResponseHeaders["Content-Length"]);
client.DownloadProgressChanged += (s, e) => progressBar1.Value = e.ProgressPercentage;
client.DownloadProgressChanged += (s, e) =>
{
lblDownloadProgress.Text = "%" + e.ProgressPercentage.ToString();
lblDownloadProgress.Left = Math.Min(
(int)(progressBar1.Left + e.ProgressPercentage / 100f * progressBar1.Width),
progressBar1.Width - lblDownloadProgress.Width
);
};
for (int i = 0; i < urls.Count; i++)
{
tracker.NewFile();
await client.DownloadFileTaskAsync(new Uri(urls[i]), @"d:\satImages\img" + i + ".gif");
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private async void btnStart_Click(object sender, EventArgs e)
{
lblStatus.Text = "Downloading...";
await DownloadAsync();
}
private void btnStop_Click(object sender, EventArgs e)
{
if (client != null)
{
client.CancelAsync();
lblStatus.Text = "Download Stopped";
}
}
static readonly string[] SizeSuffixes =
{ "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); }
if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); }
if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); }
// mag is 0 for bytes, 1 for KB, 2, for MB, etc.
int mag = (int)Math.Log(value, 1024);
// 1L << (mag * 10) == 2 ^ (10 * mag)
// [i.e. the number of bytes in the unit corresponding to mag]
decimal adjustedSize = (decimal)value / (1L << (mag * 10));
// make adjustment when the value is large enough that
// it would round up to 1000 or more
if (Math.Round(adjustedSize, decimalPlaces) >= 1000)
{
mag += 1;
adjustedSize /= 1024;
}
return string.Format("{0:n" + decimalPlaces + "} {1}",
adjustedSize,
SizeSuffixes[mag]);
}
}
}
我没有尝试 pause/resume 部分,只尝试了取消。
在顶部我添加了一个 WebClient 全局变量名称 client :
WebClient client;
在下载方法中,我在方法中引用了客户端:
并检查是否取消并在下载方法中处理客户端:
this.client = client;
client.DownloadFileCompleted += (s, e) =>
{
if (e.Cancelled)
{
client.Dispose();
return;
}
};
在 btnStop 点击事件中我添加了这段代码:
if (client != null)
{
client.CancelAsync();
lblStatus.Text = "Download Stopped";
}
在下载并单击停止按钮时,我收到此异常消息:
Cacelled getting exception
我认为您需要将 WebClient 事务包装在 BackgroundWorker 对象中,以便您可以在取消之前将 WorkerSupportsCancellation 设置为 true。那么我相信取消应该无一例外地起作用。
请参考-
https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker?view=net-5.0
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using unfreez_wrapper;
namespace Downloads
{
public partial class Form1 : Form
{
List<string> urls = new List<string>();
DownloadProgressTracker tracker;
long myLong = 0;
WebClient client;
public Form1()
{
InitializeComponent();
tracker = new DownloadProgressTracker(50, TimeSpan.FromMilliseconds(500));
lblDownloadProgress.Text = "";
lblStatus.Text = "Download Pending";
lblAmount.Text = "";
lblSpeed.Text = "";
urls.Add("https://speed.hetzner.de/10GB.bin");
urls.Add("https://speed.hetzner.de/100MB.bin");
}
private async Task DownloadAsync()
{
using (var client = new WebClient())
{
this.client = client;
client.DownloadFileCompleted += (s, e) =>
{
if (e.Cancelled)
{
client.Dispose();
return;
}
};
client.DownloadFileCompleted += (s, e) => lblStatus.Text = "Download File Completed.";
client.DownloadProgressChanged += (s, e) => tracker.SetProgress(e.BytesReceived, e.TotalBytesToReceive);
client.DownloadProgressChanged += (s, e) => lblAmount.Text = SizeSuffix(e.BytesReceived) + "/" + SizeSuffix(e.TotalBytesToReceive);
client.DownloadProgressChanged += (s, e) => lblSpeed.Text = tracker.GetBytesPerSecondString();
client.DownloadProgressChanged += (s, e) => myLong = Convert.ToInt64(client.ResponseHeaders["Content-Length"]);
client.DownloadProgressChanged += (s, e) => progressBar1.Value = e.ProgressPercentage;
client.DownloadProgressChanged += (s, e) =>
{
lblDownloadProgress.Text = "%" + e.ProgressPercentage.ToString();
lblDownloadProgress.Left = Math.Min(
(int)(progressBar1.Left + e.ProgressPercentage / 100f * progressBar1.Width),
progressBar1.Width - lblDownloadProgress.Width
);
};
for (int i = 0; i < urls.Count; i++)
{
tracker.NewFile();
await client.DownloadFileTaskAsync(new Uri(urls[i]), @"d:\satImages\img" + i + ".gif");
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private async void btnStart_Click(object sender, EventArgs e)
{
lblStatus.Text = "Downloading...";
await DownloadAsync();
}
private void btnStop_Click(object sender, EventArgs e)
{
if (client != null)
{
client.CancelAsync();
lblStatus.Text = "Download Stopped";
}
}
static readonly string[] SizeSuffixes =
{ "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
static string SizeSuffix(Int64 value, int decimalPlaces = 1)
{
if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); }
if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); }
if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); }
// mag is 0 for bytes, 1 for KB, 2, for MB, etc.
int mag = (int)Math.Log(value, 1024);
// 1L << (mag * 10) == 2 ^ (10 * mag)
// [i.e. the number of bytes in the unit corresponding to mag]
decimal adjustedSize = (decimal)value / (1L << (mag * 10));
// make adjustment when the value is large enough that
// it would round up to 1000 or more
if (Math.Round(adjustedSize, decimalPlaces) >= 1000)
{
mag += 1;
adjustedSize /= 1024;
}
return string.Format("{0:n" + decimalPlaces + "} {1}",
adjustedSize,
SizeSuffixes[mag]);
}
}
}
我没有尝试 pause/resume 部分,只尝试了取消。
在顶部我添加了一个 WebClient 全局变量名称 client :
WebClient client;
在下载方法中,我在方法中引用了客户端: 并检查是否取消并在下载方法中处理客户端:
this.client = client;
client.DownloadFileCompleted += (s, e) =>
{
if (e.Cancelled)
{
client.Dispose();
return;
}
};
在 btnStop 点击事件中我添加了这段代码:
if (client != null)
{
client.CancelAsync();
lblStatus.Text = "Download Stopped";
}
在下载并单击停止按钮时,我收到此异常消息:
Cacelled getting exception
我认为您需要将 WebClient 事务包装在 BackgroundWorker 对象中,以便您可以在取消之前将 WorkerSupportsCancellation 设置为 true。那么我相信取消应该无一例外地起作用。
请参考-
https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker?view=net-5.0