Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 加快从远程Url检索文件大小_C# - Fatal编程技术网

C# 加快从远程Url检索文件大小

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

有人能帮我加快从远程url检索文件大小吗? 我有400多个链接要检查,无需下载

我可以检查文件大小,但大约需要5分钟才能完成 总文件大小为1.45 GB

也许你可以建议如何加速

这是我目前的密码

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