در بسیاری از برنامههای نرمافزاری، علاوه بر پردازش درخواستهای کاربر، نیاز به انجام کارهای پسزمینه وجود دارد. این کارها میتوانند شامل پردازش صفها، ارسال ایمیل، جمعآوری آمار یا اجرای عملیات زمانبندیشده باشند. در .NET Core، این نیاز با استفاده از اینترفیس IHostedService و کلاس BackgroundService بهصورت استاندارد پشتیبانی میشود. این مقاله به بررسی این دو مفهوم، تفاوتها و نحوه استفاده آنها میپردازد.
IHostedService یک اینترفیس پایه برای سرویسهای پسزمینه در .NET Core است. اینترفیس شامل دو متد اصلی میشود:
public interface IHostedService { Task StartAsync(CancellationToken cancellationToken); Task StopAsync(CancellationToken cancellationToken); }
StartAsync: هنگام شروع برنامه اجرا میشود و وظیفه راهاندازی سرویس را دارد.
StopAsync: هنگام بسته شدن برنامه اجرا میشود و وظیفه توقف صحیح سرویس را برعهده دارد.
با پیادهسازی IHostedService، میتوان انواع کارهای پسزمینه مانند پردازش صفها، اجرای وظایف زمانبندیشده، یا مانیتورینگ منابع را پیادهسازی کرد.
BackgroundService یک کلاس از پیش آمادهشده است که خود IHostedService را پیادهسازی میکند و کار برنامهنویس را سادهتر میکند. کافی است کلاس خود را از BackgroundService ارثبری دهید و متد ExecuteAsync را override کنید.
using Microsoft.Extensions.Hosting; using System; using System.Threading; using System.Threading.Tasks; public class MyBackgroundService : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { Console.WriteLine($"Task running at: {DateTime.Now}"); await Task.Delay(1000, stoppingToken); } } }
در این مثال، سرویس هر ثانیه یک پیام روی کنسول چاپ میکند تا زمانی که برنامه متوقف شود. BackgroundService مدیریت لغو عملیات (cancellation) و StopAsync را بهصورت داخلی انجام میدهد، بنابراین توسعهدهنده تنها بر منطق اصلی تمرکز میکند.
ویژگیIHostedServiceBackgroundServiceسطح انتزاعپایین (اینترفیس پایه)بالا (کلاس آماده با حلقه async)پیادهسازینیاز به نوشتن StartAsync و StopAsyncفقط کافی است ExecuteAsync را override کنیدپیچیدگیبیشتر، انعطافپذیری بالاساده و مناسب اکثر کارهای پسزمینهمثال کاربردسرویسهای پیچیده با منطق سفارشیاجرای وظایف زمانبندیشده، پردازش صفها
در فایل Program.cs یا Startup.cs کافی است سرویس را به کانتینر DI اضافه کنید:
builder.Services.AddHostedService<MyBackgroundService>();
.NET Core بهصورت خودکار این سرویس را هنگام شروع برنامه اجرا کرده و هنگام خاتمه برنامه متوقف میکند.
سرویس پسزمینه باید غیرمسدودکننده باشد (از async/await استفاده شود).
اگر از IHostedService مستقیم استفاده میکنید، مدیریت حلقه و لغو عملیات باید توسط خودتان انجام شود.
BackgroundService مناسب اکثر سناریوها است و مدیریت لغو و توقف را خودکار انجام میدهد.
سرویسهای پسزمینه میتوانند همراه با برنامه وب اجرا شوند بدون آنکه درخواستهای HTTP را مسدود کنند.
در .NET Core، IHostedService و BackgroundService ابزارهای استاندارد و قوی برای اجرای کارهای پسزمینه هستند. استفاده از BackgroundService معمولاً سادهتر و کارآمدتر است، اما IHostedService انعطافپذیری بیشتری برای سناریوهای پیچیده ارائه میدهد. انتخاب بین این دو بستگی به نیاز پروژه و پیچیدگی سرویس پسزمینه دارد.
با درک این ابزارها، توسعهدهندگان میتوانند سرویسهای پسزمینه قابل اعتماد و مقیاسپذیر در برنامههای خود پیادهسازی کنند.
سناریو: ارسال ایمیلهای اطلاعرسانی کاربران
فرض کنید یک سایت فروشگاهی دارید و کاربرانی که خرید میکنند باید ایمیل تأیید سفارش دریافت کنند.
شما نمیخواهید ارسال ایمیل هنگام پاسخ HTTP مسدود شود، چون ممکن است چند ثانیه طول بکشد و کاربر منتظر بماند.
در این حالت، یک سرویس پسزمینه (Background Service) مناسب است.
ابتدا یک صف ساده برای نگهداری ایمیلها:
public class EmailQueue { private readonly Queue<string> _emails = new(); private readonly object _lock = new(); public void Enqueue(string email) { lock (_lock) { _emails.Enqueue(email); } } public string? Dequeue() { lock (_lock) { if (_emails.Count == 0) return null; return _emails.Dequeue(); } } }
using Microsoft.Extensions.Hosting; using System; using System.Threading; using System.Threading.Tasks; public class EmailSenderService : BackgroundService { private readonly EmailQueue _queue; public EmailSenderService(EmailQueue queue) { _queue = queue; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { var email = _queue.Dequeue(); if (email != null) { // شبیهسازی ارسال ایمیل Console.WriteLine($"Sending email to: {email} at {DateTime.Now}"); await Task.Delay(500); // زمان ارسال ایمیل } else { await Task.Delay(1000); // اگر ایمیلی نبود، 1 ثانیه صبر کن } } } }
var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton<EmailQueue>(); // صف ایمیل builder.Services.AddHostedService<EmailSenderService>(); // سرویس پسزمینه var app = builder.Build();
app.MapPost("/order", (string userEmail, EmailQueue queue) => { // ثبت سفارش در پایگاه داده (شبیهسازی) Console.WriteLine($"Order received for {userEmail}"); // اضافه کردن ایمیل به صف برای ارسال توسط BackgroundService queue.Enqueue(userEmail); return Results.Ok("Order placed successfully"); });
کاربر سفارش خود را ثبت میکند.
ایمیل بلافاصله به صف اضافه میشود.
سرویس پسزمینه EmailSenderService ایمیلها را به صورت مستقل و غیرمسدودکننده ارسال میکند.
پاسخ HTTP سریع است و کاربر منتظر نمیماند.
✅ مزیت: این مدل به شما امکان میدهد کارهای زمانبر یا تکراری را در پسزمینه انجام دهید، بدون اینکه تجربه کاربری تحت تأثیر قرار بگیرد.