[英]Getting error Argument 2: cannot convert from 'System.Threading.Tasks.ParallelLoopState' to 'System.Threading.CancellationToken' how to solve?
Following on:接下来:
How to download files using HttpClient with a ProgressBar?如何使用带有 ProgressBar 的 HttpClient 下载文件?
The project is WinForms .NET 6项目是WinForms .NET 6
How to solve the erro:如何解决错误:
Severity Code Description Project File Line Suppression State Error CS1503 Argument 2: cannot convert from 'System.Threading.Tasks.ParallelLoopState' to 'System.Threading.CancellationToken' WinFormsApp1 D:\Csharp\WinFormsApp1\ResourceDownloader.cs 63 Active严重性代码说明项目文件行抑制 State 错误 CS1503 参数 2:无法从“System.Threading.Tasks.ParallelLoopState”转换为“System.Threading.CancellationToken”WinFormsApp1 D:\Csharp\WinFormsApp1\ResourceDownloader.cs 63 活动
On line number 63第 63 行
var dataBytes = await client.Value.GetByteArrayAsync(site, token);
The full class code:完整的 class 代码:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace WinFormsApp1
{
public class ResourceDownloader
{
private static Lazy<HttpClient> client = new(() => {
HttpClientHandler handler = CreateHandler(autoRedirect: true);
var client = new HttpClient(handler, true) { Timeout = TimeSpan.FromSeconds(60) };
client.DefaultRequestHeaders.Add("User-Agent", @"Mozilla/5.0 (Windows NT 10; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0");
client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
client.DefaultRequestHeaders.ConnectionClose = true;
return client;
}, true);
private static HttpClientHandler CreateHandler(bool autoRedirect)
{
return new HttpClientHandler()
{
AllowAutoRedirect = autoRedirect,
CookieContainer = new CookieContainer(),
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
}
public record Website(string Url, byte[]? Data, bool Completed = true, Exception? Ex = null);
public record ProgressReport(Website Site, int PercentageComplete);
private static object syncObj = new object();
private static ConcurrentBag<Website> processed = default!;
private static int progressCount = 0;
private static int totalCount = 0;
public static bool IsBusy { get; internal set; } = false;
public static async Task<List<Website>> Download(IProgress<ProgressReport> progress, IList<string> sites, CancellationTokenSource cts)
{
IsBusy = true;
processed = new ConcurrentBag<Website>();
progressCount = 0;
totalCount = sites.Count;
try
{
ParallelOptions options = new()
{
MaxDegreeOfParallelism = 8,
CancellationToken = cts.Token
};
await Parallel.ForEach(sites, options, async (site, token) => {
try
{
var dataBytes = await client.Value.GetByteArrayAsync(site, token);
ReportProgress(progress, dataBytes, site, null);
}
catch (Exception ex)
{
ReportProgress(progress, null, site, ex);
}
});
}
// To Debug / Log
catch (TaskCanceledException) { Debug.Print("The operation was canceled"); }
finally { IsBusy = false; }
return processed.ToList();
}
private static void ReportProgress(IProgress<ProgressReport> progress, byte[]? data, string site, Exception? ex)
{
lock (syncObj)
{
progressCount += 1;
var percentage = progressCount * 100 / totalCount;
Website website = new(site, data, ex is null, ex);
processed.Add(website);
progress.Report(new ProgressReport(website, percentage));
}
}
}
}
Parallel.ForEach
is not Task
-aware and does not handle asynchronous workloads (correctly, at least), and overloads accepting handler with 2 parameters (like ForEach<TSource>(IEnumerable<TSource>, Action<TSource,ParallelLoopState>)
) use ParallelLoopState
as second parameter of the handler. Parallel.ForEach
不是Task
感知的并且不处理异步工作负载(至少正确地),并且重载接受具有 2 个参数的处理程序(如ForEach<TSource>(IEnumerable<TSource>, Action<TSource,ParallelLoopState>)
)使用ParallelLoopState
作为处理程序的第二个参数。
You need to use Parallel.ForEachAsync
(for example this overload , which accepts Func<TSource, CancellationToken, ValueTask>
) to correctly handle async workloads.您需要使用
Parallel.ForEachAsync
(例如这个 overload ,它接受Func<TSource, CancellationToken, ValueTask>
)来正确处理异步工作负载。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.