C# 加快从远程Url检索文件大小
有人能帮我加快从远程url检索文件大小吗? 我有400多个链接要检查,无需下载 我可以检查文件大小,但大约需要5分钟才能完成 总文件大小为1.45 GB 也许你可以建议如何加速 这是我目前的密码C# 加快从远程Url检索文件大小,c#,C#,有人能帮我加快从远程url检索文件大小吗? 我有400多个链接要检查,无需下载 我可以检查文件大小,但大约需要5分钟才能完成 总文件大小为1.45 GB 也许你可以建议如何加速 这是我目前的密码 public static async Task<string> GetFileSize(Uri uriPath) { var webRequest = (HttpWebRequest)WebRequest.Create(uriPath); webRequest.Method
public static async Task<string> GetFileSize(Uri uriPath)
{
var webRequest = (HttpWebRequest)WebRequest.Create(uriPath);
webRequest.Method = "HEAD";
webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36";
using (var webResponse = await webRequest.GetResponseAsync())
{
return webResponse.Headers.Get("Content-Length");
}
}
public static string FormatFileSize(long bytes)
{
var unit = 1024;
if (bytes < unit)
{
return $"{bytes} B";
}
var exp = (int)(Math.Log(bytes) / Math.Log(unit));
return $"{bytes / Math.Pow(unit, exp):F2} " +
$"{("KMGTPE")[exp - 1]}B";
}
速度受每个请求的网络/服务器响应时间的限制。 问题的关键是并行化请求。直到现在,只有在一个请求完成后,才会发出下一个请求。特别是当URI指向不同的服务器时,并行运行请求是合适的(以便表现友好,并且不会对单个服务器造成太大压力) Naive/Brute force并行化的方式是一次运行所有请求,如:
var tasks = new List<Task<string>>();
foreach (string urls in tbResult.Lines)
{
Uri url = new Uri(urls);
tasks.Add(Utils.GetFileSize(url));
}
await Task.WhenAll(tasks.ToArray());
foreach (var task in tasks) {
long info = Convert.ToInt32(task.Result);
num += info;
}
var tasks=newlist();
foreach(tbResult.line中的字符串URL)
{
Uri url=新的Uri(url);
添加(Utils.GetFileSize(url));
}
等待Task.WhenAll(tasks.ToArray());
foreach(任务中的var任务){
long info=Convert.ToInt32(task.Result);
num+=info;
}
好的,我终于找到了最好的解决方案
感谢@Ralf Bonning和@Tom W提出的联锁方法
以下是最终代码:
long sum = 0;
long localSum = 0;
var tasks = new List<Task<string>>();
foreach (string urls in URL)
{
Uri url = new Uri(urls);
tasks.Add(GetTotalBytes(url));
}
await Task.WhenAll(tasks.ToArray());
foreach (var task in tasks)
{
localSum += Convert.ToInt32(task.Result);
}
return (Utils.FormatFileSize(Interlocked.Add(ref sum, localSum)));
哇!真快!它只需要3秒的总链接:475总文件大小:1.45 GB运行时间:0h 0m 3s 64.3M我将尝试其他过程,如从url获取字符串或读取json文件,我将在成功后发布:)Bonning。你能给我举个例子说明我怎样才能取消它吗?使用cancellation Token取消流程需要1分钟。次要代码质量说明:表达式
num+=info
不是原子的,因此也不是线程安全的,因此您在这里引入了一个(可能很小的)bug。输入此表达式的两个线程在添加之前都可以读取num
的原始值,因此表达式的第二次完成会丢失参数info
,从而导致低估。为了改善这一点,你可以使用。哦,谢谢你的建议。我一直在使用它,但从现在起我会改变它:)顺便说一句,我的问题是我不能取消这个过程。取消令牌不再工作了@TomW我已经更新了代码。我使用Interlocked做得对吗?仅当您打算将1添加到数字而不是字节数时。如果要添加字节数,相当于前面的代码示例,请使用add
。实际上,我只需要总字节数,以便计算总文件大小
long sum = 0;
long localSum = 0;
var tasks = new List<Task<string>>();
foreach (string urls in URL)
{
Uri url = new Uri(urls);
tasks.Add(GetTotalBytes(url));
}
await Task.WhenAll(tasks.ToArray());
foreach (var task in tasks)
{
localSum += Convert.ToInt32(task.Result);
}
return (Utils.FormatFileSize(Interlocked.Add(ref sum, localSum)));
Total URL: 355
Filsize: 1.14 GB
Elapsed Time: 0h 0m 2s 50.8ms