Görev listesini iptal etme

Zaman uyumsuz konsol uygulamasının bitmesini beklemek istemiyorsanız iptal edebilirsiniz. Bu konudaki örneği izleyerek, bir web sitesi listesinin içeriğini indiren bir uygulamaya iptal ekleyebilirsiniz. Örneği her görevle ilişkilendirerek CancellationTokenSource birçok görevi iptal edebilirsiniz. Enter tuşunu seçerseniz henüz tamamlanmamış tüm görevleri iptal edebilirsiniz.

Bu öğreticinin içindekiler:

  • .NET konsol uygulaması oluşturma
  • İptali destekleyen zaman uyumsuz bir uygulama yazma
  • sinyal iptali gösterme

Ön koşullar

Bu öğretici için aşağıdakiler gereklidir:

Örnek uygulama oluşturma

Yeni bir .NET Core konsol uygulaması oluşturun. Komutunu kullanarak dotnet new console veya Visual Studio'dan oluşturabilirsiniz. Program.cs dosyasını sık kullandığınız kod düzenleyicisinde açın.

using deyimlerini değiştirme

Mevcut using deyimlerini şu bildirimlerle değiştirin:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

Alan ekle

Sınıf tanımına Program şu üç alanı ekleyin:

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 bir için istenen iptalin sinyalini vermek için CancellationTokenkullanılır. , HttpClient HTTP istekleri gönderme ve HTTP yanıtları alma özelliğini kullanıma sunar. , s_urlList uygulamanın işlemeyi planladığı tüm URL'leri barındırır.

Uygulama giriş noktasını güncelleştirme

Konsol uygulamasının ana giriş noktası yöntemidir Main . Mevcut yöntemi aşağıdakilerle değiştirin:

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.");
}

Güncelleştirilmiş Main yöntem artık yürütülebilir dosyaya zaman uyumsuz bir giriş noktası sağlayan Async ana değeri olarak kabul edilir. Konsola birkaç yönerge iletisi yazar, ardından konsol tuş vuruşlarını okuyacak adlı cancelTaskbir Task örnek bildirir. Enter tuşuna basılırsa çağrısı CancellationTokenSource.Cancel() yapılır. Bu, iptali işaret eder. sumPageSizesTask Ardından değişkeni yönteminden SumPageSizesAsync atanır. Daha sonra her iki görev de öğesine geçirilir Task.WhenAny(Task[])ve iki görevden herhangi biri tamamlandığında devam eder.

Sonraki kod bloğu, iptal işlemi işlenene kadar uygulamanın çıkmamasını sağlar. Tamamlanan ilk görev isecancelTasksumPageSizeTask, beklenmiştir. İptal edildiyse, beklendiğinde bir System.Threading.Tasks.TaskCanceledExceptionatar. Blok bu özel durumu yakalar ve bir ileti yazdırır.

Zaman uyumsuz toplam sayfa boyutları yöntemini oluşturma

yönteminin Main altına yöntemini ekleyin 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");
}

yöntemi, örneği oluşturarak ve başlatarak Stopwatchbaşlar. Ardından ve içindeki her URL'de s_urlList döngüye girerek öğesini çağırır ProcessUrlAsync. Her yinelemede yöntemine s_cts.TokenProcessUrlAsync geçirilir ve kod bir Task<TResult>döndürür; burada TResult bir tamsayıdır:

int total = 0;
foreach (string url in s_urlList)
{
    int contentLength = await ProcessUrlAsync(url, s_client, s_cts.Token);
    total += contentLength;
}

İşlem yöntemi ekleme

Yönteminin altına SumPageSizesAsync aşağıdaki ProcessUrlAsync yöntemi ekleyin:

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;
}

Herhangi bir URL için yöntemi, yanıtı olarak byte[]almak için sağlanan örneği kullanırclient. örneği CancellationToken ve HttpContent.ReadAsByteArrayAsync() yöntemlerine HttpClient.GetAsync(String, CancellationToken) geçirilir. token, istenen iptal için kaydolmak için kullanılır. Url ve uzunluk konsola yazıldıktan sonra uzunluk döndürülür.

Örnek uygulama çıktısı

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.

Tam örnek

Aşağıdaki kod, örnek için Program.cs dosyasının tam metnidir.

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;
    }
}

Ayrıca bkz.

Sonraki adımlar