Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questo articolo si apprenderà come usare il Task.FromResult metodo per recuperare i risultati delle operazioni di download asincrone contenute in una cache. Il FromResult metodo restituisce un oggetto finito Task<TResult> che contiene il valore fornito come proprietà Result . Questo metodo è utile quando si esegue un'operazione asincrona che restituisce un oggetto Task<TResult> e il risultato di tale oggetto Task<TResult> è già calcolato.
Esempio
L'esempio seguente scarica le stringhe dal Web. Definisce il DownloadStringAsync metodo . Questo metodo scarica le stringhe dal Web in modo asincrono. In questo esempio viene inoltre utilizzato un ConcurrentDictionary<TKey,TValue> oggetto per memorizzare nella cache i risultati delle operazioni precedenti. Se l'indirizzo di input viene mantenuto in questa cache, DownloadStringAsync usa il FromResult metodo per produrre un Task<TResult> oggetto che contiene il contenuto in tale indirizzo. In caso contrario, DownloadStringAsync scarica il file dal Web e aggiunge il risultato alla cache.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
public static class DownloadCache
{
private static readonly ConcurrentDictionary<string, string> s_cachedDownloads = new();
private static readonly HttpClient s_httpClient = new();
public static Task<string> DownloadStringAsync(string address)
{
if (s_cachedDownloads.TryGetValue(address, out string? content))
{
return Task.FromResult(content);
}
return Task.Run(async () =>
{
content = await s_httpClient.GetStringAsync(address);
s_cachedDownloads.TryAdd(address, content);
return content;
});
}
public static async Task Main()
{
string[] urls = new[]
{
"https://dotnet.territoriali.olinfo.it/aspnet/core",
"https://dotnet.territoriali.olinfo.it/dotnet",
"https://dotnet.territoriali.olinfo.it/dotnet/architecture/dapr-for-net-developers",
"https://dotnet.territoriali.olinfo.it/dotnet/azure",
"https://dotnet.territoriali.olinfo.it/dotnet/desktop/wpf",
"https://dotnet.territoriali.olinfo.it/dotnet/devops/create-dotnet-github-action",
"https://dotnet.territoriali.olinfo.it/dotnet/machine-learning",
"https://dotnet.territoriali.olinfo.it/xamarin",
"https://dotnet.microsoft.com/",
"https://www.microsoft.com"
};
Stopwatch stopwatch = Stopwatch.StartNew();
IEnumerable<Task<string>> downloads = urls.Select(DownloadStringAsync);
static void StopAndLogElapsedTime(
int attemptNumber, Stopwatch stopwatch, Task<string[]> downloadTasks)
{
stopwatch.Stop();
int charCount = downloadTasks.Result.Sum(result => result.Length);
long elapsedMs = stopwatch.ElapsedMilliseconds;
Console.WriteLine(
$"Attempt number: {attemptNumber}\n" +
$"Retrieved characters: {charCount:#,0}\n" +
$"Elapsed retrieval time: {elapsedMs:#,0} milliseconds.\n");
}
await Task.WhenAll(downloads).ContinueWith(
downloadTasks => StopAndLogElapsedTime(1, stopwatch, downloadTasks));
// Perform the same operation a second time. The time required
// should be shorter because the results are held in the cache.
stopwatch.Restart();
downloads = urls.Select(DownloadStringAsync);
await Task.WhenAll(downloads).ContinueWith(
downloadTasks => StopAndLogElapsedTime(2, stopwatch, downloadTasks));
}
// Sample output:
// Attempt number: 1
// Retrieved characters: 754,585
// Elapsed retrieval time: 2,857 milliseconds.
// Attempt number: 2
// Retrieved characters: 754,585
// Elapsed retrieval time: 1 milliseconds.
}
Imports System.Collections.Concurrent
Imports System.Net.Http
Module Snippets
Class DownloadCache
Private Shared ReadOnly s_cachedDownloads As ConcurrentDictionary(Of String, String) =
New ConcurrentDictionary(Of String, String)()
Private Shared ReadOnly s_httpClient As HttpClient = New HttpClient()
Public Function DownloadStringAsync(address As String) As Task(Of String)
Dim content As String = Nothing
If s_cachedDownloads.TryGetValue(address, content) Then
Return Task.FromResult(Of String)(content)
End If
Return Task.Run(
Async Function()
content = Await s_httpClient.GetStringAsync(address)
s_cachedDownloads.TryAdd(address, content)
Return content
End Function)
End Function
End Class
Public Sub StopAndLogElapsedTime(
attemptNumber As Integer,
stopwatch As Stopwatch,
downloadTasks As Task(Of String()))
stopwatch.Stop()
Dim charCount As Integer = downloadTasks.Result.Sum(Function(result) result.Length)
Dim elapsedMs As Long = stopwatch.ElapsedMilliseconds
Console.WriteLine(
$"Attempt number: {attemptNumber}{vbCrLf}" &
$"Retrieved characters: {charCount:#,0}{vbCrLf}" &
$"Elapsed retrieval time: {elapsedMs:#,0} milliseconds.{vbCrLf}")
End Sub
Sub Main()
Dim cache As DownloadCache = New DownloadCache()
Dim urls As String() = {
"https://dotnet.territoriali.olinfo.it/aspnet/core",
"https://dotnet.territoriali.olinfo.it/dotnet",
"https://dotnet.territoriali.olinfo.it/dotnet/architecture/dapr-for-net-developers",
"https://dotnet.territoriali.olinfo.it/dotnet/azure",
"https://dotnet.territoriali.olinfo.it/dotnet/desktop/wpf",
"https://dotnet.territoriali.olinfo.it/dotnet/devops/create-dotnet-github-action",
"https://dotnet.territoriali.olinfo.it/dotnet/machine-learning",
"https://dotnet.territoriali.olinfo.it/xamarin",
"https://dotnet.microsoft.com/",
"https://www.microsoft.com"
}
Dim stopwatch As Stopwatch = Stopwatch.StartNew()
Dim downloads As IEnumerable(Of Task(Of String)) =
urls.Select(AddressOf cache.DownloadStringAsync)
Task.WhenAll(downloads).ContinueWith(
Sub(downloadTasks)
StopAndLogElapsedTime(1, stopwatch, downloadTasks)
End Sub).Wait()
stopwatch.Restart()
downloads = urls.Select(AddressOf cache.DownloadStringAsync)
Task.WhenAll(downloads).ContinueWith(
Sub(downloadTasks)
StopAndLogElapsedTime(2, stopwatch, downloadTasks)
End Sub).Wait()
End Sub
' Sample output:
' Attempt number 1
' Retrieved characters: 754,585
' Elapsed retrieval time: 2,857 milliseconds.
'
' Attempt number 2
' Retrieved characters: 754,585
' Elapsed retrieval time: 1 milliseconds.
End Module
Nell'esempio precedente, la prima volta che viene scaricato ogni URL, il relativo valore viene archiviato nella cache. Il FromResult metodo consente al DownloadStringAsync metodo di creare Task<TResult> oggetti che contengono questi risultati pre-calcolati. Le chiamate successive per scaricare la stringa restituiscono i valori memorizzati nella cache ed è molto più veloce.