在我的应用程序中,我正在创建一些并发的Web请求,并且我对其中任何一个请求完成都感到满意,因此我使用的是Task.WhenAny:
var urls = new string[] {
"https://stackoverflow.com",
"https://superuser.com",
"https://www.reddit.com/r/chess",
};
var tasks = urls.Select(async url =>
{
using (var webClient = new WebClient())
{
return (Url: url, Data: await webClient.DownloadStringTaskAsync(url));
}
}).ToArray();
var firstTask = await Task.WhenAny(tasks);
Console.WriteLine($"First Completed Url: {firstTask.Result.Url}");
Console.WriteLine($"Data: {firstTask.Result.Data.Length:#,0} chars");
Run Code Online (Sandbox Code Playgroud)
首次完成的网址:https
://superuser.com数据:121.954个字符
我不喜欢这种实现方式,因为未完成的任务会继续下载不再需要的数据,并且浪费带宽,我希望为下一批请求保留这些带宽。因此,我正在考虑取消其他任务,但是我不确定该怎么做。我发现了如何使用CancellationToken取消特定的Web请求:
public static async Task<(string Url, string Data)> DownloadUrl(
string url, CancellationToken cancellationToken)
{
try
{
using (var webClient = new WebClient())
{
cancellationToken.Register(webClient.CancelAsync);
return (url, await webClient.DownloadStringTaskAsync(url)); …Run Code Online (Sandbox Code Playgroud) 在使用.NET async/await API时,我遇到了好奇心:循环忽略了用作超时的延迟,直到我在循环内添加了一个短暂的延迟.这是如何运作的?不是最直观的行为!
完整计划:
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main(String[] args)
{
Task.Run(async () =>
{
await Task.WhenAny(Loop(), Task.Delay(TimeSpan.FromSeconds(1)));
Console.WriteLine("Timed out!");
})
.Wait();
}
public static async Task Loop()
{
while(true)
{
// Commenting this out makes the code loop indefinitely!
await Task.Delay(TimeSpan.FromMilliseconds(1));
// This doesn't matter.
await DoWork();
}
}
public static async Task DoWork()
{
await Task.CompletedTask;
}
}
Run Code Online (Sandbox Code Playgroud)
背景
实际的程序有,while(!done)但由于一个错误done从未设置为true.循环进行多次await调用.该Task.WhenAny呼叫是在单元测试中以防止Loop() …