Aracılığıyla paylaş


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. Birçok görevi iptal etmek için örneği her görevle ilişkilendirebilirsiniz CancellationTokenSource. Enter tuşunu seçerseniz henüz tamamlanmamış tüm görevleri iptal edebilirsiniz.

Bu eğitim şunları kapsar:

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

Önkoşullar

Ö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 yönergelerini değiştirme

Mevcut using yönergeleri ş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 CancellationToken için istenen iptali belirtmek amacıyla kullanı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üncellenmiş Main metot artık yürütülebilir dosyaya zaman uyumsuz bir giriş noktası sağlayan Async ana metodu olarak kabul edilir. Konsola birkaç eğitici mesaj yazar, ardından konsol tuş vuruşlarını okuyacak Task örneğini cancelTask olarak bildirir. Enter tuşuna basıldığında CancellationTokenSource.Cancel() çağrısı yapılır. Bu, iptali işaret eder. Ardından, sumPageSizesTask değişkeni SumPageSizesAsync yönteminden atanır. İki görev de daha sonra Task.WhenAny(Task[]) öğesine aktarılır ve iki görevden herhangi biri tamamlandığında Task.WhenAny(Task[]) işlemi devam ettirir.

Sonraki kod bloğu, iptal işlemi işlenene kadar uygulamanın çıkmamasını sağlar. Eğer tamamlanacak ilk görev cancelTask ise, sumPageSizeTask beklenir. İptal edildiyse, beklendiğinde bir System.Threading.Tasks.TaskCanceledExceptionatar. Blok bu istisnayı yakalar ve bir ileti yazdırır.

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

Main metotlarının altına SumPageSizesAsync metotunu ekleyin.

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

Bu yöntem, bir Stopwatch örneği oluşturarak ve başlatarak başlar. Ardından s_urlList içindeki her URL için döngüye girer ve ProcessUrlAsync fonksiyonunu çağırır. Her yinelemede s_cts.Token, ProcessUrlAsync yöntemine 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

SumPageSizesAsync yönteminin altına aşağıdaki ProcessUrlAsync yöntemini 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;
}

Belirtilen örneği kullanarak herhangi bir URL için, yöntemin yanıtı bir byte[] olarak almasını sağlayacaktır client. CancellationToken örneği HttpClient.GetAsync(String, CancellationToken) ve HttpContent.ReadAsByteArrayAsync() yöntemlerine geçirilir. token, istenen iptal için kaydolmak için kullanılır. URL ve uzunluk konsola yazıldıktan sonra, uzunluk geri 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