برنامه نویسی

توکن های لغو در C# – انجمن DEV

سلام! 👋🏻

مدتی است که چیزی در مورد سی شارپ ننوشتم، یا به طور کلی چیزی ننوشتم، اما اکنون یک مفهوم جالب دارم که مطمئنم شما به طور تصادفی با آن برخورد کرده اید یا جایی در پایه کدهای سی شارپ دیده اید.
اگر از Entity Framework، HttpClient یا هر چیز دیگری که روش‌هایی دارد که می‌تواند کار ناهمزمان انجام دهد استفاده کرده‌اید، تقریباً تضمین شده است که اضافه بار را بپذیرید. CancellationToken آنجا حضور داشت.

پس توکن های لغو چیست؟ چرا از آنها استفاده می شود؟ فایده آنها چیست؟ دست و پنجه نرم کنید، زیرا این چیزی است که ما در این پست به آن پاسخ خواهیم داد!

تعریف نشانه های لغو 🪙

لغو در سی شارپ یک ساختار فقط خواندنی است که طبق اسناد مایکروسافت به صورت زیر تعریف می شود:

🔔 اطلاعیه ای را منتشر می کند که عملیات باید لغو شود.

معنی آن این است که نشانه لغو یک شی است که برای اعلام اینکه آیا یک عملیات باید قبل از اجرای آن لغو شود یا خیر استفاده می شود.
این مکانیسم قطعاً چیزی است که باید از آن آگاه باشید و باید در مورد نحوه استفاده و زمان استفاده از آن ایده داشته باشید.

اگر به اهمیت آن متقاعد نشده‌اید، می‌خواهم یک مثال واقعی را نشان دهم که باید برای جذب شما کافی باشد و شما را به یک طرفدار گسترده برای استفاده از نشانه‌های لغو در هر زمان ممکن تبدیل کند.

تصور کنید از وب‌سایتی مانند آمازون بازدید می‌کنید، به دسته‌بندی محصول خاصی می‌روید، و هنگامی که این کار را انجام دادید، آمازون شروع به بارگیری دسته‌ای از محصولات از آن دسته می‌کند، اما تصور کنید دسته‌بندی اشتباهی را فشار داده‌اید و بلافاصله به عقب برگشتید. با فرض اینکه آمازون از مفهوم لغو کار به طور کلی استفاده نمی‌کند، وب‌سایت همچنان به پردازش درخواست ادامه می‌دهد، حتی اگر به عقب پیمایش کرده‌اید، این کار لغو نشده است، و کوئری پایگاه داده همچنان اجرا می‌شود و داده‌هایی را برمی‌گرداند که هرگز انجام نخواهند شد. استفاده شده.

این در اصل، هدر رفتن منابع برنامه است. برنامه باید یک پرس و جو پایگاه داده بالقوه درخواستی را انجام می داد تا داده های بازیابی شده را به هیچ کجا بازگرداند. این نه تنها برای بازیابی داده ها اعمال می شود، بلکه می تواند هر عملیات دیگری مانند تماس شبکه با یک API راه دور یا عملیات IO باشد.

مبدا CancellationToken در سی شارپ 💡

اکنون که احتمالاً متقاعد شده‌اید که باید نشانه‌های لغو را در کد C# ناهمزمان خود بگنجانید، بیایید به جزئیات C# در مورد این مفهوم بپردازیم.

در سی شارپ، برای دریافت نشانه لغو، باید یک نمونه از آن ایجاد کنیم CancellationTokenSourceو از طریق آن شی منبع، می‌توانیم توکن لغو مرتبط را با استفاده از عبارت دریافت کنیم Token دارایی روی آن شی کد زیر ایجاد a را نشان می دهد CancellationToken در یک برنامه کنسول سی شارپ:


CancellationTokenSource cts = new();

CancellationToken cancellationToken = cts.Token;

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کمی در مورد CancellationTokenSource، این شیئی است که به یک نشانه لغو سیگنال می دهد که باید لغو شود، می تواند لغو فوری با فراخوانی یک نشانه لغو باشد. Cancel روش، یا CancelAfter برای تعیین زمانی که توکن باید به حالت لغو تغییر کند.

کلاس منبع دارای 4 سازنده مختلف است:

  1. CancellationTokenSource()
  2. CancellationTokenSource(int millisecondsDelay)
  3. CancellationTokenSource(TimeSpan delay)
  4. CancellationTokenSource(TimeSpan delay, TimeProvider timeProvider)

برای جمع‌بندی، همه مواردی که تاخیر دارند، نمونه‌ای ایجاد می‌کنند که پس از تأخیر ارائه‌شده در سازنده، علامت لغو روی نشانه لغو نمونه را نشان می‌دهد.

یک نمونه کدگذاری اولیه

ما تئوری صحبت کرده‌ایم، اما اکنون می‌خواهم یک قطعه کد اساسی را به شما نشان دهم، که باید به نوعی مفهوم را از نظر کد نشان دهد.


CancellationTokenSource cts = new(3000);
CancellationToken cancellationToken = cts.Token;

Task lazyCountingTask = Task.Run(() => LazyCounterFunction(cancellationToken), cancellationToken);

try
{
    await lazyCountingTask;
}
catch (OperationCanceledException ex)
{
    Console.WriteLine("Cancellation Was Requested! Lazy counter defeated");
}

static async Task LazyCounterFunction(CancellationToken cancellationToken)
{
    int counter = 0;
    while (true)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            Console.WriteLine("WE'VE BEEN COMMANDED TO CANCEL!!!");
            cancellationToken.ThrowIfCancellationRequested();
        }

        Console.WriteLine($"Counting... Currently At: {counter++}");
        Thread.Sleep(1000);
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد ارائه شده یک تابع شمارنده ایجاد می کند که هر ثانیه یک مقدار شمارنده را با شروع از 0 افزایش می دهد. در داخل حلقه while، ما IsCancellationRequested ویژگی روی نمونه نشانه لغو، به طوری که وقتی لغو فعال شد، پیامی را به کنسول وارد می کنیم و سپس تماس می گیریم ThrowIfCancellationRequested() روی آن نشانه این روش یک پرتاب می کند OperationCancelledException، که کد فراخوانی می تواند آن را بگیرد تا در صورت لغو کار، مقداری منطق را اجرا کند.

داخل Main، یک کار ایجاد می کنیم سپس آن را در داخل a منتظر می مانیم try catch مسدود کردن. با این حال، وقتی منبع رمز لغو را نمونه‌برداری کردم، رد شدم 3000 به عنوان یک استدلال برای آن، که تاخیر در میلی ثانیه است، که باید یک فرآیند 3 ثانیه را قبل از لغو شدن شبیه سازی کند.

اگر کد را اجرا کنید، باید خروجی زیر را ببینید:
خروجی نمونه کد رمز لغو

موارد استفاده واقعی از نشانه های لغو ⚙️

اکنون با خارج شدن از برنامه نمونه شمارنده، اجازه دهید برخی از موارد استفاده در دنیای واقعی را بررسی کنیم که مزایای توکن های لغو را برجسته می کند.


[HttpGet("get-users")]
public async Task<IActionResult> GetUsersAsync(CancellationToken cancellationToken)
{
    try
    {
        var users = await UsersRepo.GetAllUsersAsync(cancellationToken);

        return Ok(users);
    }
    catch (OperationCanceledException ex)
    {
        return Ok("Cancelled loading users query");
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با شروع با این نقطه پایانی API آزمایشی، این نقطه پایانی قرار است تمام کاربران موجود در پایگاه داده را بارگیری کند و آنها را برگرداند.

⚠️ لطفا توجه داشته باشید که این یک پیاده سازی ناقص است، در چنین سناریویی، باید انواع دیگر استثناها را مدیریت کنید، صفحه بندی، فیلتر کردن و موارد دیگر را اضافه کنید.

در پارامترهای نقطه پایانی خود، ما یک پارامتر نشانه لغو اضافه کردیم، اکنون وقتی یک سرویس را با استفاده از آن می نویسید HttpClient به عنوان مثال، برای فراخوانی این نقطه پایانی، می‌توانید یک نشانه لغو ارسال کنید که همانطور که قبلاً گفتیم، می‌توانید از یک شی منبع نشانه لغو دریافت کنید و شاید در رابط کاربری با تکیه بر آن سرویس http، می‌توانید یک دکمه لغو اضافه کنید یا علامت بزنید. برای زمانی که کاربر از صفحه حرکت می کند، اگر کار هنوز انجام نشده بود، می توانید با آن تماس بگیرید Cancel روشی به گونه ای که کار به درستی لغو شود.

توکن های لغو با هسته چارچوب موجودیت 🗂️

هنگام استفاده از Async انواع روش‌های Entity Framework Core LINQ، همیشه با اضافه‌باری مواجه می‌شوید که توکن لغو را می‌پذیرد، و اکنون از آنجایی که نحوه استفاده از این ابزار قدرتمند را یاد گرفته‌اید، همیشه باید در صورت امکان یکی را پاس کنید.

بیایید این قطعه کد را بررسی کنیم:


public class EventsManagementService
{
    private readonly ApplicationDbContext _dbContext;

    public EventsManagementService(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<List<LogStore>> GetEventsAsync(CancellationToken cancellationToken)
    {
        // Use AsNoTracking() to avoid change tracking overhead
        var events = await _dbContext.LogStore.AsNoTracking().ToListAsync(cancellationToken);
        return events;
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در این کلاس سرویس مدیریت رویدادها، ما متدی داریم که لیستی از آنها را بازیابی می کند LogStore اشیاء، روش یک نشانه لغو را می پذیرد که به آن منتقل می شود ToListAsync روش. این روش از EF Core به طور ناهمزمان یک لیست از یک ایجاد می کند IQueryable با برشمردن نتایج حاصل از پرس و جو. به این ترتیب، هنگامی که لغو درخواست می شود، این روش به ایجاد لیست ادامه نمی دهد و بنابراین برنامه ما را از منابع سوخته ذخیره می کند.

نتیجه

در این پست به طور کلی مفهوم لغو کار و نحوه عملکرد آن در سی شارپ را بررسی کردیم. من نمی خواستم زیاد در تئوری غوطه ور شوم، اما در عوض کد واقعی را به شما نشان می دهم تا مفهوم در حال استفاده را ببینید. اکنون که با این دانش جدید مجهز شده‌اید، می‌توانید به آرامی یک نشانه لغو دریافت کنید، یک تأخیر لغو تنظیم کنید و در واقع یک عملیات همگام‌سازی را لغو کنید.
امیدوارم از این پست چیز جدیدی یاد گرفته باشید!

با تشکر برای خواندن!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا