如何使用 HttpWebRequest 获得文件并行

2024-01-01

我正在尝试制作一个像 IDM 这样的程序,它可以同时下载文件的部分内容。
我用来实现此目的的工具是 C# .Net4.5 中的 TPL
但是我在使用的时候遇到了问题Tasks使操作并行。
序列功能运行良好,并且正在正确下载文件。
使用任务的并行函数一直在工作,直到发生奇怪的事情:
我创建了 4 个任务,其中Factory.StartNew(),在每个任务中给出了开始位置和结束位置,任务将下载这些文件,然后它将以 byte[] 形式返回,一切都很顺利,任务工作正常,但在某些时候,执行冻结了,就这样,程序停止了,没有其他事情发生。
并行函数的实现:

static void DownloadPartsParallel()
    {

        string uriPath = "http://mschnlnine.vo.llnwd.net/d1/pdc08/PPTX/BB01.pptx";
        Uri uri = new Uri(uriPath);
        long l = GetFileSize(uri);
        Console.WriteLine("Size={0}", l);
        int granularity = 4;
        byte[][] arr = new byte[granularity][];
        Task<byte[]>[] tasks = new Task<byte[]>[granularity];
        tasks[0] = Task<byte[]>.Factory.StartNew(() => DownloadPartOfFile(uri, 0, l / granularity));
        tasks[1] = Task<byte[]>.Factory.StartNew(() => DownloadPartOfFile(uri, l / granularity + 1, l / granularity + l / granularity));
        tasks[2] = Task<byte[]>.Factory.StartNew(() => DownloadPartOfFile(uri, l / granularity + l / granularity + 1, l / granularity + l / granularity + l / granularity));
        tasks[3] = Task<byte[]>.Factory.StartNew(() => DownloadPartOfFile(uri, l / granularity + l / granularity + l / granularity + 1, l));//(l / granularity) + (l / granularity) + (l / granularity) + (l / granularity)


        arr[0] = tasks[0].Result;
        arr[1] = tasks[1].Result;
        arr[2] = tasks[2].Result;
        arr[3] = tasks[3].Result;
        Stream localStream;
        localStream = File.Create("E:\\a\\" + Path.GetFileName(uri.LocalPath));
        for (int i = 0; i < granularity; i++)
        {

            if (i == granularity - 1)
            {
                for (int j = 0; j < arr[i].Length - 1; j++)
                {
                    localStream.WriteByte(arr[i][j]);
                }
            }
            else
                for (int j = 0; j < arr[i].Length; j++)
                {
                    localStream.WriteByte(arr[i][j]);
                }
        }
    }

DownloadPartOfFile函数实现:

public static byte[] DownloadPartOfFile(Uri fileUrl, long from, long to)
    {
        int bytesProcessed = 0;
        BinaryReader reader = null;
        WebResponse response = null;
        byte[] bytes = new byte[(to - from) + 1];

        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fileUrl);
            request.AddRange(from, to);
            request.ReadWriteTimeout = int.MaxValue;
            request.Timeout = int.MaxValue;
            if (request != null)
            {
                response = request.GetResponse();
                if (response != null)
                {
                    reader = new BinaryReader(response.GetResponseStream());
                    int bytesRead;
                    do
                    {
                        byte[] buffer = new byte[1024];
                        bytesRead = reader.Read(buffer, 0, buffer.Length);
                        if (bytesRead == 0)
                        {
                            break;
                        }
                        Array.Resize<byte>(ref buffer, bytesRead);
                        buffer.CopyTo(bytes, bytesProcessed);
                        bytesProcessed += bytesRead;
                        Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ",Downloading" + bytesProcessed);
                    } while (bytesRead > 0);
                }
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            if (response != null) response.Close();
            if (reader != null) reader.Close();
        }

        return bytes;
    }

我尝试通过设置int.MaxValue读取超时、写入读取超时、写入超时来解决这个问题,这就是程序冻结的原因,如果我不这样做,在函数DownloadPartsParallel中就会出现超时异常
那么有没有解决方案,或者任何其他可能有帮助的建议,谢谢。


我会用HttpClient.SendAsync http://msdn.microsoft.com/en-us/library/hh138176(v=vs.110).aspx而不是WebRequest (see “HttpClient 来了!” http://blogs.msdn.com/b/henrikn/archive/2012/02/11/httpclient-is-here.aspx).

我不会使用任何额外的线程。 The HttpClient.SendAsyncAPI 本质上是异步的并返回一个可等待的Task<>,无需将其卸载到池线程Task.Run/Task.TaskFactory.StartNew (see this https://stackoverflow.com/q/21690385/1768303进行详细讨论)。

我还会限制并行下载的数量SemaphoreSlim.WaitAsync()。以下是我对控制台应用程序的看法(未经广泛测试):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace Console_21737681
{
    class Program
    {
        const int MAX_PARALLEL = 4; // max parallel downloads
        const int CHUNK_SIZE = 2048; // size of a single chunk

        // a chunk of downloaded data
        class Chunk
        {
            public long Start { get; set; }
            public int Length { get; set; }
            public byte[] Data { get; set; }
        };

        // throttle downloads
        SemaphoreSlim _throttleSemaphore = new SemaphoreSlim(MAX_PARALLEL);

        // get a chunk
        async Task<Chunk> GetChunk(HttpClient client, long start, int length, string url)
        {
            await _throttleSemaphore.WaitAsync();
            try
            {
                using (var request = new HttpRequestMessage(HttpMethod.Get, url))
                {
                    request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(start, start + length - 1);
                    using (var response = await client.SendAsync(request))
                    {
                        var data = await response.Content.ReadAsByteArrayAsync();
                        return new Chunk { Start = start, Length = length/*, Data = data*/ };
                    }
                }
            }
            finally
            {
                _throttleSemaphore.Release();
            }
        }

        // download the URL in parallel by chunks
        async Task<Chunk[]> DownloadAsync(string url)
        {
            using (var client = new HttpClient())
            {
                var request = new HttpRequestMessage(HttpMethod.Head, url);
                var response = await client.SendAsync(request);
                var contentLength = response.Content.Headers.ContentLength;

                if (!contentLength.HasValue)
                    throw new InvalidOperationException("ContentLength");

                var numOfChunks = (int)((contentLength.Value + CHUNK_SIZE - 1) / CHUNK_SIZE);

                var tasks = Enumerable.Range(0, numOfChunks).Select(i =>
                {
                    // start a new chunk
                    long start = i * CHUNK_SIZE;
                    var length = (int)Math.Min(CHUNK_SIZE, contentLength.Value - start);
                    return GetChunk(client, start, length, url);
                }).ToList();

                await Task.WhenAll(tasks);

                // the order of chunks is random
                return tasks.Select(task => task.Result).ToArray();
            }
        }

        static void Main(string[] args)
        {
            var program = new Program();
            var chunks = program.DownloadAsync("http://flaglane.com/download/australian-flag/australian-flag-large.png").Result;

            Console.WriteLine("Chunks: " + chunks.Count());
            Console.ReadLine();
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 HttpWebRequest 获得文件并行 的相关文章

  • 删除文件的最后 10 个字符

    我想删除文件的最后 10 个字符 说一个字符串 hello i am a c learner 是文件内的数据 我只是希望该文件是 hello i am a 文件的最后 10 个字符 即字符串 c learner 应在文件内消除 解决方案 将
  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 为什么 GCC 不允许我创建“内联静态 std::stringstream”?

    我将直接前往 MCVE include
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 无限循环与无限递归。两者都是未定义的吗?

    无副作用的无限循环是未定义的行为 看here https coliru stacked crooked com view id 24e0a58778f67cd4举个例子参考参数 https en cppreference com w cpp
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 如何在 Linq to SQL 中使用distinct 和 group by

    我正在尝试将以下 sql 转换为 Linq 2 SQL select groupId count distinct userId from processroundissueinstance group by groupId 这是我的代码
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • C++ 中的参考文献

    我偶尔会在 StackOverflow 上看到代码 询问一些涉及函数的重载歧义 例如 void foo int param 我的问题是 为什么会出现这种情况 或者更确切地说 你什么时候会有 对参考的参考 这与普通的旧参考有何不同 我从未在现
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • 位计数法

    谁能解释一下这个比特计数方法 public static int bitCount int i Hacker s Delight Figure 5 2 i i gt gt 1 0x55555555 i i 0x33333333 i gt g
  • 在 Windows 资源管理器中右键单击使用 VSCode 打开,没有重新打开以前的文件

    描述 当我使用右键菜单中的 使用 VS Code 打开 从 Windows 资源管理器中打开选定的文件时 VSCode 仅打开我选择的文件 它没有像sublime那样重新打开以前的文件 有什么办法可以改变这种行为吗 已经设置 window
  • Ruby on Rails - params 是方法还是哈希?

    所以 我正在尝试入门Ruby on Rails 指南部分here http guides rubyonrails org getting started html 我不明白line http guides rubyonrails org g
  • web.config IIS 中的 PHP(或其他)CGI 配置

    我最近开发了一个 Web 应用程序的安装程序 是的 带有安装程序的 Web 应用程序 使用维克斯工具套装 http wixtoolset org 该向导引导用户获取站点安装所需的所有基本信息 如下所示 在安装结束时使用自定义操作 我使用动态
  • 如何捕获实体数据源异常

    我有一个绑定到实体数据源的 gridview 我使用工具箱中的 asp net 控件拖放并使用实体数据模型创建了它 我在代码隐藏中几乎没有输入 出于测试目的 我编辑了网格视图并添加了无效的数据 然后我单击更新以引发异常 所以我的问题是我想尝
  • 如何将正常的 for 循环复制到 *ngFor

    rating 4 for i 0 i lt rating i print statement 如何使用 ngFor 在角度 6 中复制相同的 for 循环 循环应根据评级值运行 如果是 2 则应运行 2 次 我想你正在寻找这种解决方案 只需
  • 使变量最后出现在调用堆栈中

    我有一个包含一些字段的类 我需要按值比较此类的实例 所以我定义了GetHashCode and Equals因此 因为该类允许循环引用 所以我需要一种机制来避免无限递归 更详细的解释请参见值等于和循环引用 如何解决无限递归 https st
  • 使用pom文件从目标目录中删除或删除资源文件

    我在 pom xml 中有两个配置文件 并且有一些资源文件已添加到目标资源目录中 project build outputDirectory resources在执行第一个配置文件期间 我需要做的是在执行第二个配置文件期间删除这些资源文件
  • 为什么 isEmoji 实例属性对数字返回 true?

    Problem Why isEmoji实例属性对于数字返回 true 检查下面的示例 let scalars Unicode Scalar 1 for s in scalars print s gt s properties isEmoji
  • Flutter 如何只给容器边框底部

    在 Flutter 中如何仅设置底部边框 如下图所示 我有一个带有文本的容器 从底部显示红色边框 请指导如何仅从底部设置边框 Use Border与bottom争论 Container decoration BoxDecoration bo
  • 在 v-for 循环内选择 vue 2 中的特定元素

    请看代码 div div v if msg last sender click prevent loadMsg msg gt tr some html tr div loadMsg obj obj isActive obj isActive
  • Thread#run 和 Thread#wakeup 之间的区别?

    在 Ruby 中 有什么区别线程 运行 http www ruby doc org core 1 9 3 Thread html method i run and 主题 wakup http www ruby doc org core 1
  • 从 ReactNative-DatePickerAndroid 获取选定日期

    我正在关注React Native DatePicker Android 文档 https facebook github io react native docs datepickerandroid html 对于 DatePickerI
  • Python中的运算符重载:处理不同类型和顺序的参数[重复]

    这个问题在这里已经有答案了 我有一个简单的类 可以帮助对向量 即数字列表 进行数学运算 我的Vector可以乘以其他实例Vector or标量 float or int 在其他更强类型的语言中 我将创建一种方法来将两个相乘vectors 和
  • 具有条件更新的 DynamoDBContext

    在我的应用程序中 我使用亚马逊对象持久性模型并使用 DynamoDBContext 进行操作 CURD 和执行查询 我需要知道如何使用 DynamoDBContext 进行条件更新 并且它应该是异步的 我知道使用亚马逊低级 API 的方法
  • 给定 RNG 算法和一系列数字,是否可以确定哪个种子会产生该系列?

    代码是用 Objective C 写的 但即使你不了解 Objective C 如果你仔细看一下它应该是可以理解的 基本上它是一个 RNG 对象 你实例化一个新实例 如果需要的话设置种子并开始抓取随机数 那么是否可以回溯给定的一系列数字来确
  • css & html:隐藏边框的一角[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有以下用户界面 我只想隐藏三种颜色的 div 的一角 它应该看起来像这样 任何人都可以知道如何隐藏 div 边框的角 这是我要求的代
  • 错误 2003 (HY000):无法连接到 AWS RDS 上的 MySQL 服务器

    我创建了一个具有 主机名的外部用户以允许远程访问 将本地 MySQL 连接到远程 AWS RDS 时出现以下错误 错误 2003 HY000 无法连接到 instance cvxqy8tbi2bk us east 1 rds amazona
  • Android XML 解析省略“&”

    问题又是 虽然我在代码中成功实现了 SAX 解析器 但它的行为很奇怪 它只是跳过 之后的条目并转到下一个条目 只是想知道这是否是 SAX 解析器的典型工作方式还是我错误地实现了它 我已经实现了 org xml sax ContentHand
  • 如何使用 HttpWebRequest 获得文件并行

    我正在尝试制作一个像 IDM 这样的程序 它可以同时下载文件的部分内容 我用来实现此目的的工具是 C Net4 5 中的 TPL但是我在使用的时候遇到了问题Tasks使操作并行 序列功能运行良好 并且正在正确下载文件 使用任务的并行函数一直