程序在没有调试器的情况下运行不同
Program runs differently without debugger
我有一个程序 (.NET 5) 使用 WebClient.DownloadFile 同时下载一堆文件 (1k+)调试和发布模式下的文件;但是当运行退出调试器时,它无法下载超过 50% 的文件。
所有线程都在程序结束前完成,因为它们是前台线程。
程序代码为:
using System;
using System.IO;
using System.Net;
using System.Threading;
namespace Dumper
{
internal sealed class Program
{
private static void Main(string[] args)
{
Directory.CreateDirectory(args[1]);
foreach (string uri in File.ReadAllLines(args[0]))
{
string filePath = Path.Combine(args[1], uri.Split('/')[^1]);
new Thread((param) =>
{
(string path, string url) = ((string, string))param!;
using WebClient webClient = new();
try
{
webClient.DownloadFile(new Uri(url.Replace("%", "%25")), path);
Console.WriteLine($"{path} has been successfully download.");
}
catch (UriFormatException)
{
throw;
}
catch (Exception e)
{
Console.WriteLine($"{path} failed to download: {e}");
}
}).Start((filePath, uri));
}
}
}
}
您的问题与调试无关,但一般而言,您的代码存在很多问题。这是一个更明智的方法,将等待所有下载完成。
注意:您也可以使用 Task.WhenAll
,但是我选择使用 TPL 数据流 ActionBlock
以防您需要管理并行度
给定
private static readonly HttpClient _client = new();
private static string _basePath;
private static async Task ProcessAsync(string input)
{
try
{
var uri = new Uri(Uri.EscapeUriString(input));
var filePath = Path.Combine(_basePath, input.Split('/')[^1]);
using var result = await _client
.GetAsync(uri)
.ConfigureAwait(false);
// fail fast
result.EnsureSuccessStatusCode();
await using var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, 1024 * 1024, FileOptions.Asynchronous);
await using var stream = await result.Content
.ReadAsStreamAsync()
.ConfigureAwait(false);
await stream.CopyToAsync(fileStream)
.ConfigureAwait(false);
Console.WriteLine($"Downloaded : {uri}");
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
用法
private static async Task Main(string[] args)
{
var file = args.ElementAtOrDefault(0) ?? @"D:\test.txt";
_basePath = args.ElementAtOrDefault(1) ?? @"D:\test";
Directory.CreateDirectory(_basePath);
var actionBlock = new ActionBlock<string>(ProcessAsync,new ExecutionDataflowBlockOptions()
{
EnsureOrdered = false,
MaxDegreeOfParallelism = -1 // set this if you think the site is throttling you
});
foreach (var uri in File.ReadLines(file))
await actionBlock.SendAsync(uri);
actionBlock.Complete();
// wait to make sure everything is completed
await actionBlock.Completion;
}