我目前有一个链接到图片或MP4文件的网址列表,重新编码运行速度更快的最佳方法是什么?我知道我可以运行多个线程甚至是并行但最好的方式是什么?我不要太担心速度,只要它不像现在这么慢,但我不想过度使用设备的资源,例如CPU试图加快速度
sock
答案 0 :(得分:2)
Jimi 在评论中向我指出,DownloadFileAsync是一个事件驱动的电话而不是等待。但是,有一个WebClient.DownloadFileTaskAsync版本,在此示例中使用的是适当的版本,它是一个等待的调用并返回Task
将指定资源作为异步下载到本地文件 使用任务对象进行操作。
我知道我可以运行多个线程甚至是并行但最重要的是 最好的方式
是的,您可以使其并行并控制您使用的资源。
只要它没有那么慢,我就不会太担心速度 现在,但我不想过度使用CPU等设备的资源 试图加快速度
你应该能够实现这一点,并且相当好地配置
好的,所以有很多方法可以做到这一点。以下是一些需要考虑的事项
async
/ await
模式执行此操作,这样您就不会在IO完成端口上浪费系统资源或粉碎CPU 一些直接的解决方案
asnyc
/ await
模式中的WaitAll
,这是一个很好的方法,但是限制并发任务有点棘手。Parallel.ForEach
和Parallel.For
,这有一个很好的方法来限制并发工作负载,但它不适合IO绑定任务请注意:还有很多其他方法
所以Parallel.ForEach
使用线程池。此外, IO绑定操作将阻止那些等待设备响应并占用资源的线程。一般的经验法则是
Parallel.ForEach
是合适的; 在这种情况下,下载文件显然是 I / O ,有DownloadFileAsync
版本和1000个要下载的文件,因此您最好使用async
/ await
模式和某些类型的并发任务限制
以下是如何实现此目标的一个非常基本的示例
鉴于
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
}
}
摘要
这种方法为您提供了 Asynchrony ,它还为您提供了MaxDegreeOfParallelism
,它不会浪费资源,并且让 IO 成为 IO
*免责声明,DataFlow可能不是您想要的地方,但我只是认为id会为您提供更多信息
*免责声明2 ,上述代码尚未经过测试,我会认真考虑先研究这项技术并彻底尽职尽责。
答案 1 :(得分:1)
将您的功能标记为async
并使用DownloadFileAsync
保存文件。在返回之前,将任务列表捕获到一个新列表中,并await
列出Task.WhenAll(yourTasks)
列表。
答案 2 :(得分:0)
您可以使用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 ",
}
}
}
}