Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.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# 下载1000+;文件快吗?_C#_.net - Fatal编程技术网

C# 下载1000+;文件快吗?

C# 下载1000+;文件快吗?,c#,.net,C#,.net,我目前有一个链接到图像或MP4文件的URL列表,什么是最好的方法来重新编码以运行得更快?我知道我可以运行多个线程,甚至并行,但最好的方法是什么?我不太担心速度,只要它没有现在那么慢,但我不想过度使用设备的资源,比如CPU,试图加速它 public static void Download(string saveLocation, List<string> urls) { using (var client = new WebClient()) { fo

我目前有一个链接到图像或MP4文件的URL列表,什么是最好的方法来重新编码以运行得更快?我知道我可以运行多个线程,甚至并行,但最好的方法是什么?我不太担心速度,只要它没有现在那么慢,但我不想过度使用设备的资源,比如CPU,试图加速它

public static void Download(string saveLocation, List<string> urls)
{
    using (var client = new WebClient())
    {
        foreach (var url in urls)
        {
            Console.WriteLine("Downloading: " + url);
            client.DownloadFile(url, saveLocation + "/" + url.Split('/').Last());
        }
    }
}
publicstaticvoid下载(字符串保存位置,列表URL)
{
使用(var client=new WebClient())
{
foreach(url中的变量url)
{
Console.WriteLine(“下载:+url”);
client.DownloadFile(url,saveLocation+“/”+url.Split(“/”).Last());
}
}
}

将您的函数标记为
async
并使用
下载文件async
保存文件。将任务列表捕获到一个新列表中,然后用
Task.whalll(您的任务)
等待该列表,然后返回。

更新 Jimi刚刚在评论中向我指出,这是一个事件驱动的电话,不可等待。尽管有一个版本,在本例中使用它是合适的,但它是一个等待的调用,并返回一个
任务

将指定的资源作为异步文件下载到本地文件 使用任务对象的操作

原始答案 我知道我可以运行多个线程,甚至可以并行运行,但问题是什么 最佳方式

是的,你可以使它并行并控制你使用的资源

我不太担心速度,只要速度不慢就行 现在,但我不想让设备的资源(如CPU)功率过大 试图加快速度

您应该能够实现这一点,并将其配置得相当好


好的,有很多方法可以做到这一点。这里有一些事情需要考虑

  • 您有1000个任务(指定给任务)
  • 对于这么多的文件,您需要某种并行性,并能够配置并发任务的数量
  • 您将希望以
    异步
    /
    等待
    模式执行此操作,这样您就不会在IO完成端口上浪费系统资源或损坏CPU
一些直接的解决办法

  • 任务,在asnyc/
    等待
    模式中,这是一个很好的方法,但是限制并发任务有点棘手
  • 您有和,这是一种很好的限制并发工作负载的方法,但它不适合IO绑定的任务
  • 你可以考虑的另一个选择是微软,我最近很喜欢这些图书馆,因为它们可以给你两个世界最好的东西。李>
请注意:还有许多其他方法

因此,
Parallel.ForEach
使用线程池。此外,IO绑定操作将阻止那些等待设备响应并占用资源的线程。这里的一般经验法则是

  • 如果您有CPU绑定的代码,
    Parallel.ForEach
    是合适的
  • 虽然如果您有IO绑定的代码,异步是合适的
在这种情况下,下载文件显然是I/O,有一个
DownloadFileAsync
版本,需要下载1000个文件,因此最好使用
async
/
wait
模式和对并发任务的某种类型的限制


下面是一个非常基本的示例,说明如何实现这一点

给定的

public class WorkLoad
{
    public string Url {get;set;}
    public string FileName {get;set;}

}
数据流示例

public async Task DoWorkLoads(List<WorkLoad> workloads)
{
   var options = new ExecutionDataflowBlockOptions
                     {
                        // add pepper and salt to taste
                        MaxDegreeOfParallelism = 50
                     };

   // create an action block
   var block = new ActionBlock<WorkLoad>(MyMethodAsync, options);

   // Queue them up
   foreach (var workLoad in workloads)
      block.Post(workLoad );

   // wait for them to finish
   block.Complete();
   await block.Completion;

}

...

// Notice we are using the async / await pattern
public async Task MyMethodAsync(WorkLoad workLoad)
{

    try
    {
        Console.WriteLine("Downloading: " + workLoad.Url);
        await client.DownloadFileAsync(workLoad.Url, workLoad.FileName);
    }
    catch (Exception)
    {
        // probably best to add some error checking some how
    }
}
公共异步任务工作负载(列出工作负载)
{
var options=新的ExecutionDataflowBlockOptions
{
//加入胡椒粉和盐调味
MaxDegreeOfParallelism=50
};
//创建一个动作块
var block=新操作块(MyMethodAsync,选项);
//让他们排队
foreach(工作负载中的var工作负载)
区块.员额(工作量);
//等待他们完成
block.Complete();
等待区块完成;
}
...
//注意,我们使用的是异步/等待模式
公共异步任务MyMethodAsync(工作负载)
{
尝试
{
控制台.WriteLine(“下载:”+workLoad.Url);
等待client.DownloadFileAsync(workLoad.Url,workLoad.FileName);
}
捕获(例外)
{
//可能最好添加一些错误检查一些方法
}
}
摘要

public class WorkLoad
{
    public string Url {get;set;}
    public string FileName {get;set;}

}
这种方法提供了异步性,还提供了
MaxDegreeOfParallelism
,不浪费资源,让IO成为IO

*免责声明,数据流可能不在您想要的位置,但我想我会给您提供更多信息

<强> >免责声明2 < /强>,上述代码未经测试,我将认真考虑首先研究此技术并认真执行您的尽职调查。



您可以使用Parallel.ForEach并行下载文件。我过去也用过类似的东西

    using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace FileDownloader
{
    class Program
    {
        static void Main(string[] args)
        {
            List allUrls = GetUrls().Select(x=>x.Trim()).ToList();

            Parallel.ForEach(allUrls, new ParallelOptions() { MaxDegreeOfParallelism = 10 }, url =>
            {
                try
                {
                    WebRequest request = WebRequest.Create(url);
                    WebResponse response = request.GetResponse();
                    string originalFileName = response.ResponseUri.AbsolutePath.Substring(response.ResponseUri.AbsolutePath.LastIndexOf("/") + 1);
                    Stream streamWithFileBody = response.GetResponseStream();
                    using (Stream output = File.OpenWrite(@"C:\Ebooks_New\" + originalFileName))
                    {
                        streamWithFileBody.CopyTo(output);
                    }

                    Console.WriteLine("Downloded : " + originalFileName);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Unable to Download : " + ex.ToString());

                }
            });

            Console.WriteLine("Finished : ************************");
            Console.ReadKey();
        }

        public static List GetUrls()
        {
            return new List() // Put list of URLs here
            {
                "http://ligman.me/1IW1oab  ",
    "http://ligman.me/1Uixtlq  ",
    "http://ligman.me/1R9Ubgt  ",
    "http://ligman.me/1H4VXHT  ",
    "http://ligman.me/1f8XUKy  ",
    "http://ligman.me/1HBEUPi  ",
    "http://ligman.me/1NDTZR4  ",
    "http://ligman.me/1Uiy2f9  ",
    "http://ligman.me/1epZ0QU  ",
    "http://ligman.me/1JIhgjA  ",
    "http://ligman.me/1CQX5uG  ",
   }
  }
 }
}

这方面的一个代码示例将非常有用,我不确定为什么我需要一个任务列表以及它是如何工作的。显然,为每个下载(500+)创建一个任务是不好的,那么我将如何对下载进行分区呢?我在这里看到一个问题,因为
DownloadFileAsync
是不可等待的,它是事件驱动的。这将从方法声明中踢出async,而
ActionBlock
将发出抱怨。@jimi谢谢你,这让我的整个spiel无效。我会尽快修改的。我不知道我怎么会错过这个答案。我刚刚试过,它只是有一个小问题,
客户端
没有声明,尽管我希望您刚刚为它创建了一个新的web客户端。除此之外,回答得很好,谢谢。刚才注意到我在尝试等待
DownloadFileAsync
时似乎遇到了一个错误,因为它也是一个无效的返回类型。@user692959239您需要使用DownloadFileT