[英]Download multiple files in parallel using c#
我想使用 C# 並行下載文件。 為此,我編寫了這段運行良好的代碼,但問題是 UI 凍結了。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace FileDownloader
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private static int count = 1;
private static string f= "lecture";
private string URL = "www.someexample.com";
public MainWindow()
{
InitializeComponent();
}
public static string GetDirectoryListingRegexForUrl(string url)
{
if (url.Equals(URL))
{
return "<a href=\".*\">(?<name>.*)</a>";
}
throw new NotSupportedException();
}
public void DownloadP(string[] urls)
{
Parallel.ForEach(urls.ToList(), new ParallelOptions { MaxDegreeOfParallelism = 10 }, DownloadFile);
}
private void DownloadFile(string url)
{
using(WebClient client=new WebClient())
{
if (url.EndsWith(".pdf"))
{
int nextIndex = Interlocked.Increment(ref count);
client.DownloadFile(url, f + nextIndex + ".pdf");
this.Dispatcher.Invoke(() => {
listbox.Items.Add(url);
});
}
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DownloadP(listofFiles);
}
}
}
您可以將async/await
與新的WebClient
方法DownloadFileTaskAsync
結合使用。
private async Task DownloadFile(string url)
{
if (!url.EndsWith(".pdf"))
{
return;
}
using (var client = new WebClient())
{
int nextIndex = Interlocked.Increment(ref count);
await client.DownloadFileTaskAsync(url, "lecture" + nextIndex + ".pdf");
listBox.Items.Add(url);
}
}
private async void Button_OnClick(object sender, RoutedEventArgs e)
{
button.IsEnabled = false;
await DownloadFiles(urlList);
button.IsEnabled = true;
}
private async Task DownloadFiles(IEnumerable<string> urlList)
{
foreach (var url in urlList)
{
await DownloadFile(url);
}
}
而不是使用client.DownloadFile使用client.DownloadFileAsync這樣
var webClient=new WebClient();
webClient.DownloadFileCompleted += webClient_DownloadFileCompleted;
webClient.DownloadFileAsync("Your url","file_name");
事件
private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("Download Completed.");
}
我知道這個問題很舊,但是 WebClient 已經過時且專用。 首先,WPF 使用您應該嘗試遵循的 MVVM 模式,但除了您可以在using System.Net.Http;
.
要並行下載多個文件,您可以創建一個並行的 foreach 來處理 HttpClient 必須執行的所有下載。 你做對了,但是 foreach 會阻塞線程,所以在一個新的Task.Run(()=>{// Your Code});
如果您不想自己編寫類似的東西,您可以使用 NuGet 上的碎片下載庫。 這個 NuGet 包也在 GitHub 上,如果你想看看它是如何工作的。 如果我想下載很多文件,它經常幫助我,因為它不會阻塞 UI 線程並且易於使用。 要使用它你必須寫這樣的東西:
void Download()
{
string[] links = new string[]{
"https://google.com",
"https://speed.hetzner.de/100MB.bin",
"https://file-examples.com/storage/fe88dacf086398d1c98749c/2017/04/file_example_MP4_1920_18MG.mp4" };
foreach (var link in links)
{
_ = new LoadRequest(link);
}
Console.ReadLine();
}
但是您也可以設置 MaxDegreeOfParalism 並且可以在下載時更改它。 您可以設置輸出文件的路徑並為其命名。 HttpClient 的下載完成和進度報告的問題也由此解決。 不好的是這個庫的文檔不是很好。 這里以幾個選項為例。
async Task DownloadAsync()
{
string[] links = new string[]{
"https://google.com",
"https://speed.hetzner.de/100MB.bin",
"https://file-examples.com/storage/fe88dacf086398d1c98749c/2017/04/file_example_MP4_1920_18MG.mp4" };
RequestHandler requestHandler = new()
{
MaxDegreeOfParallelism = 10
};
LoadRequestOptions option = new()
{
Progress = new Progress<float>(value => Console.WriteLine(value.ToString("0.0%"))),
DestinationPath = "C:\\Users\\[UserName]\\Desktop\\",
RequestCompleated = path => Console.WriteLine("Finished: " + path?.ToString()),
RequestHandler = requestHandler
};
LoadRequest last = null;
foreach (string link in links)
{
last = new LoadRequest(link, option);
}
await last.Task;
}
我希望這可以幫助那些有同樣問題並且不想使用專用 WebClient 的人。
用以下方法重新啟動DownloadP功能:
public async Task DownloadP(string[] urls)
{
await Task.Factory.StartNew(() => Parallel.ForEach(urls.ToList(), new ParallelOptions { MaxDegreeOfParallelism = 10 }, DownloadFile));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.