Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Anda dapat membatalkan aplikasi konsol asinkron jika Anda tidak ingin menunggunya selesai. Dengan mengikuti contoh dalam topik ini, Anda dapat menambahkan pembatalan ke aplikasi yang mengunduh konten daftar situs web. Anda dapat membatalkan banyak tugas dengan mengaitkan instans CancellationTokenSource dengan setiap tugas. Jika Anda memilih kunci Enter, Anda membatalkan semua tugas yang belum selesai.
Tutorial ini mencakup:
- Membuat aplikasi konsol .NET
- Menulis aplikasi asinkron yang mendukung pembatalan
- Menunjukkan cara pembatalan sinyal
Prasyarat
- .NET SDK terbaru
- Visual Studio Code editor
- The C# DevKit
Membuat aplikasi contoh
Buat aplikasi konsol .NET Core baru. Anda dapat membuatnya dengan menggunakan perintah dotnet new console
atau dari Visual Studio. Buka file Program.cs di editor kode favorit Anda.
Ganti menggunakan direktif
Ganti arahan using
yang ada dengan deklarasi ini:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
Tambah bidang
Dalam definisi kelas Program
, tambahkan tiga bidang ini:
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"
};
CancellationTokenSource digunakan untuk menandakan permintaan pembatalan ke CancellationToken.
HttpClient
mengekspos kemampuan untuk mengirim permintaan HTTP dan menerima respons HTTP.
s_urlList
menyimpan semua URL yang rencananya akan diproses aplikasi.
Memperbarui titik entri aplikasi
Titik masuk utama ke dalam aplikasi konsol adalah metode Main
. Ganti metode yang ada dengan yang berikut ini:
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.");
}
Metode Main
yang diperbarui sekarang dianggap sebagai metode utama asinkron , yang memungkinkan titik masuk asinkron ke dalam program yang dapat dieksekusi. Ini menulis beberapa pesan instruksi ke konsol, lalu mendeklarasikan instans Task bernama cancelTask
, yang akan membaca goresan kunci konsol. Jika tombol Enter ditekan, panggilan ke CancellationTokenSource.Cancel() dilakukan. Ini akan menjadi sinyal pembatalan. Selanjutnya, variabel sumPageSizesTask
ditetapkan dari metode SumPageSizesAsync
. Kedua tugas kemudian diteruskan ke Task.WhenAny(Task[]), yang akan berlanjut ketika salah satu dari dua tugas telah selesai.
Blok kode berikutnya memastikan bahwa aplikasi tidak keluar sampai pembatalan telah diproses. Jika tugas pertama yang harus diselesaikan adalah cancelTask
, maka sumPageSizeTask
ditunggu. Jika dibatalkan, saat ditunggu memunculkan System.Threading.Tasks.TaskCanceledException. Blok menangkap pengecualian itu, dan mencetak pesan.
Buat fungsi asinkron untuk menjumlahkan ukuran halaman
Di bawah metode Main
, tambahkan metode SumPageSizesAsync
:
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");
}
Metode ini dimulai dengan menginstansiasi dan memulai Stopwatch. Kemudian melakukan perulangan melalui setiap URL di s_urlList
dan memanggil ProcessUrlAsync
. Dengan setiap iterasi, s_cts.Token
diteruskan ke metode ProcessUrlAsync
dan kode mengembalikan Task<TResult>, di mana TResult
adalah bilangan bulat:
int total = 0;
foreach (string url in s_urlList)
{
int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
total += contentLength;
}
Menambahkan metode proses
Tambahkan metode ProcessUrlAsync
berikut di bawah metode SumPageSizesAsync
:
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;
}
Untuk URL tertentu, metode akan menggunakan instans client
yang disediakan untuk mendapatkan respons sebagai byte[]
. Instans CancellationToken diteruskan ke metode HttpClient.GetAsync(String, CancellationToken) dan HttpContent.ReadAsByteArrayAsync().
token
digunakan untuk mendaftarkan pembatalan yang diminta. Panjang dikembalikan setelah URL dan panjang ditulis ke dalam konsol.
Contoh output aplikasi
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.
Contoh lengkap
Kode berikut adalah teks lengkap file Program.cs untuk contoh.
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;
}
}