اجرای تسکهای پسزمینه (Background Tasks) در ASP.NET Core ⚙️
در این مقاله در مورد اجرای تسکهای پسزمینه در ASP.NET Core صحبت خواهیم کرد. پس از خواندن این مقاله، شما قادر خواهید بود یک تسک پسزمینه را راهاندازی کرده و در عرض چند دقیقه آن را اجرا کنید.
تسکهای پسزمینه برای انتقال برخی کارها در اپلیکیشن شما به پسزمینه، خارج از جریان عادی اپلیکیشن، استفاده میشوند. یک مثال معمول میتواند پردازش غیرهمزمان پیامها از یک صف باشد. 📨
در این پست به شما نشان خواهیم داد که چگونه یک تسک پسزمینه ساده ایجاد کنید که یک بار اجرا شده و به پایان میرسد.
و همچنین خواهید دید که چگونه یک تسک پسزمینه مداوم را پیکربندی کنید، که پس از یک دوره زمانی مشخص تکرار میشود.
تسکهای پسزمینه با IHostedService 🔌
شما میتوانید یک تسک پسزمینه را با پیادهسازی اینترفیس IHostedService تعریف کنید. این اینترفیس فقط دو متد دارد.
public interface IHostedService
{
Task StartAsync(CancellationToken cancellationToken);
Task StopAsync(CancellationToken cancellationToken);
}
تمام کاری که باید انجام دهید پیادهسازی متدهای StartAsync و StopAsync است.
در داخل StartAsync شما معمولاً پردازش پسزمینه را انجام میدهید. و در داخل StopAsync هرگونه پاکسازی لازم، مانند آزاد کردن منابع، را انجام میدهید.
برای پیکربندی تسک پسزمینه باید متد AddHostedService را فراخوانی کنید:
builder.Services.AddHostedService<MyBackgroundTask>();
فراخوانی AddHostedService، تسک پسزمینه را به عنوان یک سرویس singleton پیکربندی میکند.
پس آیا تزریق وابستگی در پیادهسازیهای IHostedService هنوز کار میکند؟
بله، اما شما فقط میتوانید سرویسهای transient یا singleton را تزریق کنید.
با این حال، من دوست ندارم خودم اینترفیس IHostedService را پیادهسازی کنم. در عوض، ترجیح میدهم از کلاس BackgroundService استفاده کنم.
تسکهای پسزمینه با BackgroundService 👍
کلاس BackgroundService از قبل اینترفیس IHostedService را پیادهسازی کرده است و یک متد abstract دارد که شما باید آن را override کنید - ExecuteAsync. وقتی از کلاس BackgroundService استفاده میکنید، فقط باید به عملیاتی که میخواهید پیادهسازی کنید فکر کنید.
در اینجا یک مثال از تسک پسزمینه برای اجرای مایگریشنهای EF آمده است:
public class RunEfMigrationsBackgroundTask : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
public RunEfMigrationsBackgroundTask(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using IServiceScope scope = _serviceProvider.CreateScope();
await using AppDbContext dbContext =
scope.ServiceProvider.GetRequiredService<AppDbContext>();
await dbContext.Database.MigrateAsync(stoppingToken);
}
}
DbContext
در EF یک سرویس scoped است، که ما نمیتوانیم آن را مستقیماً داخل RunEfMigrationsBackgroundTask تزریق کنیم. ما باید یک نمونه از IServiceProvider را تزریق کنیم که میتوانیم از آن برای ایجاد یک service scope سفارشی استفاده کنیم، تا بتوانیم AppDbContext scoped را resolve کنیم.
من توصیه نمیکنم RunEfMigrationsBackgroundTask را در پروداکشن اجرا کنید. مایگریشنهای EF به راحتی میتوانند شکست بخورند و شما با مشکل مواجه خواهید شد. با این حال، فکر میکنم برای توسعه محلی کاملاً مناسب است.