Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Sie können eine asynchrone Konsolenanwendung abbrechen, wenn Sie nicht warten möchten, bis sie abgeschlossen ist. Wenn Sie dem Beispiel in diesem Thema folgen, können Sie eine Abbruchmöglichkeit in eine Anwendung integrieren, die den Inhalt einer Liste von Websites herunterlädt. Sie können viele Aufgaben abbrechen, indem Sie die CancellationTokenSource Instanz den einzelnen Aufgaben zuordnen. Wenn Sie die EINGABETASTE auswählen, brechen Sie alle Noch nicht abgeschlossenen Aufgaben ab.
In diesem Lernprogramm wird Folgendes behandelt:
- Erstellen einer .NET-Konsolenanwendung
- Schreiben einer asynchronen Anwendung, die den Abbruch unterstützt
- Demonstrieren der Signalunterdrückung
Voraussetzungen
- Das neueste .NET SDK
- Visual Studio Code Editor
- Das C# DevKit
Beispielanwendung erstellen
Erstellen Sie eine neue .NET Core-Konsolenanwendung. Sie können eine erstellen, indem Sie den dotnet new console Befehl oder visual Studio verwenden. Öffnen Sie die Program.cs Datei in Ihrem bevorzugten Code-Editor.
Ersetzen mithilfe von Direktiven
Ersetzen Sie die vorhandenen using Direktiven durch diese Deklarationen:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
Hinzufügen von Feldern
Fügen Sie in der Program Klassendefinition die folgenden drei Felder hinzu:
static readonly CancellationTokenSource s_cts = new CancellationTokenSource();
static readonly HttpClient s_client = new HttpClient
{
MaxResponseContentBufferSize = 1_000_000
};
static readonly IEnumerable<string> s_urlList = new string[]
{
"https://learn.microsoft.com",
"https://learn.microsoft.com/aspnet/core",
"https://learn.microsoft.com/azure",
"https://learn.microsoft.com/azure/devops",
"https://learn.microsoft.com/dotnet",
"https://learn.microsoft.com/dynamics365",
"https://learn.microsoft.com/education",
"https://learn.microsoft.com/enterprise-mobility-security",
"https://learn.microsoft.com/gaming",
"https://learn.microsoft.com/graph",
"https://learn.microsoft.com/microsoft-365",
"https://learn.microsoft.com/office",
"https://learn.microsoft.com/powershell",
"https://learn.microsoft.com/sql",
"https://learn.microsoft.com/surface",
"https://learn.microsoft.com/system-center",
"https://learn.microsoft.com/visualstudio",
"https://learn.microsoft.com/windows",
"https://learn.microsoft.com/maui"
};
Dieses CancellationTokenSource wird verwendet, um einem CancellationToken einen angeforderten Abbruch zu signalisieren. Dies HttpClient macht die Möglichkeit zum Senden von HTTP-Anforderungen und zum Empfangen von HTTP-Antworten verfügbar.
s_urlList enthält alle URLs, die von der Anwendung verarbeitet werden sollen.
Aktualisieren des Einstiegspunkts der Anwendung
Der Haupteinstiegspunkt in die Konsolenanwendung ist die Main Methode. Ersetzen Sie die vorhandene Methode durch Folgendes:
static async Task Main()
{
Console.WriteLine("Application started.");
Console.WriteLine("Press the ENTER key to cancel...\n");
Task cancelTask = Task.Run(() =>
{
while (Console.ReadKey().Key != ConsoleKey.Enter)
{
Console.WriteLine("Press the ENTER key to cancel...");
}
Console.WriteLine("\nENTER key pressed: cancelling downloads.\n");
s_cts.Cancel();
});
Task sumPageSizesTask = SumPageSizesAsync();
Task finishedTask = await Task.WhenAny(new[] { cancelTask, sumPageSizesTask });
if (finishedTask == cancelTask)
{
// wait for the cancellation to take place:
try
{
await sumPageSizesTask;
Console.WriteLine("Download task completed before cancel request was processed.");
}
catch (TaskCanceledException)
{
Console.WriteLine("Download task has been cancelled.");
}
}
Console.WriteLine("Application ending.");
}
Die aktualisierte Main Methode gilt nun als Async Main, das einen asynchronen Einstiegspunkt in der ausführbaren Datei ermöglicht. Es schreibt ein paar Anweisungsmeldungen in die Konsole und deklariert dann eine Task Instanz namens cancelTask, die Konsolentastenstriche liest. Wenn die EINGABETASTE gedrückt wird, wird ein Aufruf CancellationTokenSource.Cancel() getätigt. Dies wird die Stornierung signalisieren. Als Nächstes wird die sumPageSizesTask Variable der SumPageSizesAsync Methode zugewiesen. Beide Vorgänge werden dann an Task.WhenAny(Task[])übergeben, die fortgesetzt werden, wenn eine der beiden Vorgänge abgeschlossen ist.
Der nächste Codeblock stellt sicher, dass die Anwendung erst beendet wird, wenn die Abbruchanforderung verarbeitet worden ist. Wenn die erste abzuschließende Aufgabe der cancelTask ist, wird der sumPageSizeTask erwartet. Falls sie abgebrochen wurde, wird beim Erwarten ein System.Threading.Tasks.TaskCanceledException ausgelöst. Der Block fängt diese Ausnahme ab und druckt eine Nachricht.
Asynchrone Methode zur Summierung von Seitengrößen erstellen
Fügen Sie unter der Main Methode die SumPageSizesAsync Methode hinzu:
static async Task SumPageSizesAsync()
{
var stopwatch = Stopwatch.StartNew();
int total = 0;
foreach (string url in s_urlList)
{
int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
total += contentLength;
}
stopwatch.Stop();
Console.WriteLine($"\nTotal bytes returned: {total:#,#}");
Console.WriteLine($"Elapsed time: {stopwatch.Elapsed}\n");
}
Die Methode beginnt mit dem Instanziieren und Starten eines Stopwatch. Anschließend iteriert es über jede URL in den s_urlList und ruft ProcessUrlAsync auf. Bei jeder Iteration wird s_cts.Token in die Methode ProcessUrlAsync übergeben, und der Code gibt ein Task<TResult> zurück, wobei TResult eine ganze Zahl ist.
int total = 0;
foreach (string url in s_urlList)
{
int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
total += contentLength;
}
Hinzufügen einer Prozessmethode
Fügen Sie die folgende ProcessUrlAsync Methode unter der SumPageSizesAsync Methode hinzu:
static async Task<int> ProcessUrlAsync(string url, HttpClient client, CancellationToken token)
{
HttpResponseMessage response = await client.GetAsync(url, token);
byte[] content = await response.Content.ReadAsByteArrayAsync(token);
Console.WriteLine($"{url,-60} {content.Length,10:#,#}");
return content.Length;
}
Für jede angegebene URL nutzt die Methode die Instanz client, um die Antwort als byte[] zu erhalten. Die CancellationToken Instanz wird an die HttpClient.GetAsync(String, CancellationToken) Und HttpContent.ReadAsByteArrayAsync() Methoden übergeben. Die token wird verwendet, um sich für die Stornierung auf Anfrage zu registrieren. Die Länge wird zurückgegeben, nachdem die URL und die Länge in die Konsole geschrieben wurden.
Beispielanwendungsausgabe
Application started.
Press the ENTER key to cancel...
https://learn.microsoft.com 37,357
https://learn.microsoft.com/aspnet/core 85,589
https://learn.microsoft.com/azure 398,939
https://learn.microsoft.com/azure/devops 73,663
https://learn.microsoft.com/dotnet 67,452
https://learn.microsoft.com/dynamics365 48,582
https://learn.microsoft.com/education 22,924
ENTER key pressed: cancelling downloads.
Application ending.
Vollständiges Beispiel
Der folgende Code ist der vollständige Text der Program.cs-Datei für das Beispiel.
using System.Diagnostics;
class Program
{
static readonly CancellationTokenSource s_cts = new CancellationTokenSource();
static readonly HttpClient s_client = new HttpClient
{
MaxResponseContentBufferSize = 1_000_000
};
static readonly IEnumerable<string> s_urlList = new string[]
{
"https://learn.microsoft.com",
"https://learn.microsoft.com/aspnet/core",
"https://learn.microsoft.com/azure",
"https://learn.microsoft.com/azure/devops",
"https://learn.microsoft.com/dotnet",
"https://learn.microsoft.com/dynamics365",
"https://learn.microsoft.com/education",
"https://learn.microsoft.com/enterprise-mobility-security",
"https://learn.microsoft.com/gaming",
"https://learn.microsoft.com/graph",
"https://learn.microsoft.com/microsoft-365",
"https://learn.microsoft.com/office",
"https://learn.microsoft.com/powershell",
"https://learn.microsoft.com/sql",
"https://learn.microsoft.com/surface",
"https://learn.microsoft.com/system-center",
"https://learn.microsoft.com/visualstudio",
"https://learn.microsoft.com/windows",
"https://learn.microsoft.com/maui"
};
static async Task Main()
{
Console.WriteLine("Application started.");
Console.WriteLine("Press the ENTER key to cancel...\n");
Task cancelTask = Task.Run(() =>
{
while (Console.ReadKey().Key != ConsoleKey.Enter)
{
Console.WriteLine("Press the ENTER key to cancel...");
}
Console.WriteLine("\nENTER key pressed: cancelling downloads.\n");
s_cts.Cancel();
});
Task sumPageSizesTask = SumPageSizesAsync();
Task finishedTask = await Task.WhenAny(new[] { cancelTask, sumPageSizesTask });
if (finishedTask == cancelTask)
{
// wait for the cancellation to take place:
try
{
await sumPageSizesTask;
Console.WriteLine("Download task completed before cancel request was processed.");
}
catch (OperationCanceledException)
{
Console.WriteLine("Download task has been cancelled.");
}
}
Console.WriteLine("Application ending.");
}
static async Task SumPageSizesAsync()
{
var stopwatch = Stopwatch.StartNew();
int total = 0;
foreach (string url in s_urlList)
{
int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
total += contentLength;
}
stopwatch.Stop();
Console.WriteLine($"\nTotal bytes returned: {total:#,#}");
Console.WriteLine($"Elapsed time: {stopwatch.Elapsed}\n");
}
static async Task<int> ProcessUrlAsync(string url, HttpClient client, CancellationToken token)
{
HttpResponseMessage response = await client.GetAsync(url, token);
byte[] content = await response.Content.ReadAsByteArrayAsync(token);
Console.WriteLine($"{url,-60} {content.Length,10:#,#}");
return content.Length;
}
}