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