CodeGym /Kurslar /C# SELF /Asinxron əməliyyatların ləğvi

Asinxron əməliyyatların ləğvi

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Giriş

Siz asinxron (və ya uzunmüddətli) əməliyyatı başladanda, istifadəçi (və ya başqa kod) birdən deyə bilər: "Dayan! Artıq lazım deyil! Dayan!". Məsələn, istifadəçi nəhəng faylın yüklənməsini ləğv edə, proqram pəncərəsini bağlaya və ya böyük verilənlər bazasında axtarışı ləğv edə bilər. Ləğv dəstəyi olmasa, programınız boşuna işləməyə və resursları yeyməyə davam edə bilər — istifadəçi və kompüter üçün yaxşı deyil.

Ləğv üçün tipik ssenarilər:

  • Fayl yükləməsinin ləğvi və ya məlumatların göndərilməsinin ləğvi.
  • İstifadəçinin tələbiylə mürəkkəb məlumat emalından tez çıxmaq.
  • Uzunmüddətli işin qəfil dayandırılması/pausası, artıq aktuallığını itirmişsə.

Ləğv — istifadəçi dostu, reaktiv və resurslara qənaət edən tətbiqlər üçün sizin gizli inqrediyentinizdir.

.NET-də asinxron əməliyyatları necə ləğv etmək olar?

.NET-də uzunmüddətli tapşırıqları ləğv etmək üçün "ləğv tokeni" (CancellationToken) konsepti istifadə olunur. Bu xüsusi obyekt tapşırığın bütün komponentlərinə ötürülür. Kimsə əməliyyatı ləğv etməyi xahiş edərsə — token dərhal bu haqda proqramın bütün maraqlı hissələrinə xəbər verir. Praktikada bu qırmızı bayraq kimidir: kim birinci görsə — dayanacaq.

.NET-də bu mexanizm iki əsas siniflə reallaşdırılıb:

Vacib: öz-özünə ləğv tokeni kodun icrasını kəsmir, o yalnız "siqnal" verir — tətbiqiniz isə bu siqnala necə və nə zaman reaksiya verəcəyinə özü qərar verir.

2. Ləğv tokeni yaradırıq və tapşırığı ləğv edirik

Gəlin sadə nümunə ilə göstərək (tədris konsol tətbiqimizi inkişaf etdirəcəyik).

Nümunə: ləğvlə sadə asinxron əməliyyat


using System;
using System.Threading;
using System.Threading.Tasks;

namespace DemoApp
{
    class Program
    {
        static async Task Main()
        {
            // CancellationTokenSource yaradırıq
            CancellationTokenSource cts = new CancellationTokenSource();

            // Asinxron tapşırığı işə salırıq
            Task longRunningTask = DoWorkAsync(cts.Token);

            Console.WriteLine("Əməliyyatı ləğv etmək üçün hər hansı düyməni basın...");
            Console.ReadKey();

            // Ləğv tələb edirik
            cts.Cancel();

            try
            {
                await longRunningTask;
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine("Əməliyyat ləğv edildi!");
            }
        }

        // Ləğvi dəstəkləyən asinxron metod
        static async Task DoWorkAsync(CancellationToken cancellationToken)
        {
            for (int i = 0; i < 10; i++)
            {
                // Ləğv siqnalını yoxlayırıq
                cancellationToken.ThrowIfCancellationRequested();

                Console.WriteLine($"Addımın icrası {i + 1}/10...");
                await Task.Delay(1000); // 1 saniyə gecikmə
            }

            Console.WriteLine("Əməliyyat uğurla başa çatdı!");
        }
    }
}

Bu necə işləyir?

- Biz CancellationTokenSource (cts) yaradırıq və ondan token (cts.Token) alırıq.
- Bu tokeni asinxron əməliyyatımıza ötürürük.
- DoWorkAsync() daxilində müntəzəm olaraq tokeni ThrowIfCancellationRequested() ilə yoxlayırıq. Əgər istifadəçi tapşırığın ləğvini tələb edərsə — metod OperationCanceledException atacaq və tapşırıq dayandırılacaq.
- Main() daxilində hər hansı düymənin basılmasını gözləyir və cts.Cancel() çağırırıq ki, dayandırmaq tələbini "siqnal edək".

Əgər siz cancellationToken.IsCancellationRequested yoxlamazsanız və ya ThrowIfCancellationRequested() çağırmazsanız, tapşırığınız olduğu kimi işləməyə davam edəcək — token yalnız informasiya bayrağıdır.

3. CancellationToken: necə qurulub? Bir az sehr

Ləğv tokeni — metodlar və tapşırıqlar arasında rahatlıqla ötürülə bilən obyektdir. Bu bir neçə üstünlük verir:

  • Eyni token bir neçə asinxron və sinxron əməliyyatda istifadə oluna bilər.
  • Bir CancellationTokenSource-dan gələn token istifadə olunursa, "qrup ləğvi" təşkil etmək olar — bütün tapşırıqlar bir anda ləğv edilir.
  • Ləğv tokeni həddindən artıq müdaxiləçi deyil: onu görməzdən gətsəniz, kod əvvəlki kimi işləyir.

Ləğvi idarə etmək: tokeni harada və necə yoxlamalı?

Ləğv bayrağının qaldırılıb-qaldırılmadığını yoxlamaq məntiqə uyğun olan yerlərdə lazımdır: dövrədə, uzun emalın hər addımında, mərhələlər arasında və s.


// Hər hansı bir yoxlama anında
if (cancellationToken.IsCancellationRequested)
{
    Console.WriteLine("Əməliyyat ləğv edildi! Çıxırıq...");
    return;
}

// Və ya belə (qısa və istisna ilə)
cancellationToken.ThrowIfCancellationRequested();

Adətən ThrowIfCancellationRequested() istifadə olunur — o xüsusi istisna atır və onu çağıran kodda tutmaq olar.

4. Standart kitabxananın asinxron metodları

Çoxlu .NET sinifləri və metodları (xüsusilə asinxron olanlar) CancellationToken-i "qutudan çıxanda" dəstəkləyir. Bunlardan istifadə edərək əməliyyatları düzgün dayandırmaq mümkündür və tövsiyə olunur.

Faylı asinxron oxuma nümunəsi:


using System.IO;
using System.Threading;
using System.Threading.Tasks;

class FileDemo
{
    public static async Task ReadFileWithCancelAsync(string filePath, CancellationToken cancellationToken)
    {
        using FileStream stream = File.OpenRead(filePath);
        byte[] buffer = new byte[4096];

        int bytesRead;
        while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0)
        {
            // Məlumatı emal edirik...
            // Əgər ləğv tokeni tələb edilibsə, ReadAsync özü OperationCanceledException atacaq
        }
    }
}

FileStream.ReadAsync və CancellationToken haqqında daha ətraflı rəsmi sənədlərdə oxuyun.

5. Faydalı nüanslar

Timeout — o da ləğvdir!

Siz əməliyyatları müəyyən vaxt keçdikdən sonra avtomatik olaraq ləğv edə bilərsiniz. Bunun üçün CancellationTokenSource-u "vaxtla" yaratmaq olar:


// Məsələn, 5 saniyəlik timeout ilə CancellationTokenSource yaratmaq
CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));

Beş (5) saniyədən sonra token avtomatik olaraq "qaldırılacaq" və onunla işləyən əməliyyatlar növbəti yoxlamada dayandırılacaq. Bu əbədi gözləmək istəmədiyiniz hallarda çox rahatdır.

Ləğv zamanı nə baş verir?

Siz CancellationTokenSource üzərində Cancel() çağırdıqda, həmin tokeni istifadə edən və onun vəziyyətini yoxlayan bütün metodlar bu dəyişikliyi görəcəklər. Amma əgər sizin kod tokeni yoxlamırsa — ləğv baş verməyəcək.

Tipik səhv: tokeni bütün asinxron və uzun əməliyyatlara ötürməyi unutmaq. Bu halda əməliyyatın bir hissəsi ləğv edilə, bir hissəsi isə işləməyə davam edə bilər.

Vizualizasiya: ləğv necə keçir

sequenceDiagram
    participant Main as Baş thread
    participant CTS as CancellationTokenSource
    participant Task as Asinxron tapşırıq

    Main->>CTS: CTS yaradır, token alır
    Main->>Task: tokeni asinxron tapşırığa ötürür
    Note over Task: Tapşırıq dövri olaraq tokeni yoxlayır
    Main->>CTS: Cancel() çağırır
    CTS-->>Task: token "ləğv edildi" statusu alır
    Task-->>Main: OperationCanceledException atır
    Main->>Main: istisnanı tutur və işi bitirir

Ləğv harada tətbiq olunur?

  • Asinxron yükləmələr və server sorğuları: pis internet və ya yorulan istifadəçi zamanı ləğv etmək olar.
  • Böyük hesablamalar: timeout və ya istifadəçi tələbi ilə dayandırmaq olar.
  • Şəbəkə əməliyyatları, fayllarla iş, fon rejimində böyük kolleksiyaların emalı.

Beləliklə, asinxron əməliyyatların ləğvi ilə tanışlıq bitdi — indi tətbiqiniz təkcə sürətli deyil, həm də daha diqqətli olacaq!

6. Tövsiyələr və tipik səhvlər

Unutmayın cancellation tokeni bütün dəstəkləyən metodlara və çağırışlara ötürmək. Əgər haradasa tokeni ötürməsəniz — əməliyyat "yapışa" və dayanmaya bilər.

Tokeni müntəzəm yoxlayın — xüsusən uzun dövrlərdə, fayl emalında və ya böyük həcmdə yükləmələrdə. IsCancellationRequested və ya ThrowIfCancellationRequested() istifadə edin.

Sən demə "bəsitcə" söndürməyə çalışmayın: xaricdən thread-i və ya task-ı zorla bitirməyə çalışmaq olmaz — ləğv tokeni xahişdir, zorakılıq deyil.

Standart kitabxananın ReadAsync, Delay, HttpClient.SendAsync və s. kimi funksiyaları artıq token vasitəsilə ləğvi dəstəkləyir. Onlardan istifadə edin!

Ləğvi emal edərkən məhz OperationCanceledException-ı tutun — bu ləğvin düzgün və istək əsasında baş verdiyini bildirən xüsusi istisnadır.

1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
Fayllarla Asinxron Əməliyyatlar
Fayllarla asinxron işləməyin üstünlükləri
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION