using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Threading.Tasks;
private static readonly ConcurrentDictionary<string, string> cachedDownloads = new();
private static readonly HttpClient httpClient = new();
public static async Task Main()
var message = await GreetingAsync();
Console.WriteLine(message);
"https://docs.microsoft.com/aspnet/core",
"https://docs.microsoft.com/dotnet",
"https://docs.microsoft.com/dotnet/azure",
"https://docs.microsoft.com/dotnet/machine-learning",
"https://docs.microsoft.com/xamarin",
IEnumerable<Task<string>> downloads1 = urls.Select(DownloadAsync);
await Task.WhenAll(downloads1);
IEnumerable<Task<string>> downloads2 = urls.Select(DownloadAsync);
await Task.WhenAll(downloads2);
private static Task<string> GreetingAsync() {
return Task.FromResult("Hello World");
private static Task<string> DownloadAsync(string address)
if(cachedDownloads.TryGetValue(address, out string content)){
Console.WriteLine($"Reading {address} data from cache");
return Task.FromResult(content);
return Task.Run(async () => {
var content = await httpClient.GetStringAsync(address);
cachedDownloads.TryAdd(address, content);
Console.WriteLine($"Reading {address} data from web");