C# Academy · Pelajaran

IHostedService & BackgroundService

Implementasikan IHostedService dan BackgroundService abstrak untuk menjalankan pekerjaan di latar belakang dalam host .NET.

Pelajaran 1 dari 412 langkah

IHostedService & BackgroundService adalah pelajaran C# Academy gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar C# Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus C# Academy mencakup 4 pelajaran total.

Apa Itu Layanan Latar Belakang?

Layanan latar belakang menjalankan pekerjaan jangka panjang bersama aplikasi ASP.NET Core Anda — memproses antrean, menjalankan tugas terjadwal, atau memantau sumber daya. .NET menyediakan dua antarmuka: IHostedService (minimal) dan BackgroundService abstrak (cocok untuk perulangan).

Antarmuka IHostedService

IHostedService memiliki dua metode: StartAsync (dipanggil saat host dimulai) dan StopAsync (dipanggil selama penghentian secara bertahap). Antarmuka ini ideal untuk tugas mulai dan berhenti sekali jalan.

public class DatabaseMigratorService : IHostedService
{
    private readonly IServiceScopeFactory _scopeFactory;

    public DatabaseMigratorService(IServiceScopeFactory sf) => _scopeFactory = sf;

    public async Task StartAsync(CancellationToken ct)
    {
        using var scope = _scopeFactory.CreateScope();
        var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
        await db.Database.MigrateAsync(ct);
    }

    public Task StopAsync(CancellationToken ct) => Task.CompletedTask;
}

builder.Services.AddHostedService<DatabaseMigratorService>();

BackgroundService: Perulangan Jangka Panjang

BackgroundService adalah kelas abstrak yang mengimplementasikan IHostedService dan menyediakan ExecuteAsync(CancellationToken) — metode yang berjalan selama siklus hidup aplikasi.

public class HeartbeatService : BackgroundService
{
    private readonly ILogger<HeartbeatService> _logger;

    public HeartbeatService(ILogger<HeartbeatService> l) => _logger = l;

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        _logger.LogInformation("Heartbeat service started");

        while (!ct.IsCancellationRequested)
        {
            _logger.LogInformation("Heartbeat: {Time}", DateTime.UtcNow);
            await Task.Delay(TimeSpan.FromSeconds(30), ct);
        }

        _logger.LogInformation("Heartbeat service stopping");
    }
}

builder.Services.AddHostedService<HeartbeatService>();

Menggunakan Layanan dengan Cakupan

Layanan latar belakang bersifat Singleton. Untuk menggunakan layanan dengan cakupan (seperti DbContext), selalu buat cakupan baru untuk setiap unit pekerjaan menggunakan IServiceScopeFactory.

public class DataSyncService : BackgroundService
{
    private readonly IServiceScopeFactory _factory;
    private readonly ILogger<DataSyncService> _log;

    public DataSyncService(IServiceScopeFactory f, ILogger<DataSyncService> l)
    { _factory = f; _log = l; }

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            using (var scope = _factory.CreateScope())
            {
                var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
                await SyncDataAsync(db, ct);
            } // scope and DbContext disposed here

            await Task.Delay(TimeSpan.FromMinutes(5), ct);
        }
    }
}

Penghentian Secara Bertahap

Saat host dihentikan, host akan memicu token pembatalan. ExecuteAsync Anda harus memantau token tersebut dan melakukan pembersihan. Secara bawaan, host menunggu hingga 5 detik sebelum menghentikan proses secara paksa.

protected override async Task ExecuteAsync(CancellationToken ct)
{
    try
    {
        while (!ct.IsCancellationRequested)
        {
            await DoWorkAsync(ct);
            await Task.Delay(1000, ct);
        }
    }
    catch (OperationCanceledException)
    {
        // Normal shutdown — not an error
        _logger.LogInformation("Service stopping due to cancellation");
    }
    finally
    {
        // Cleanup
        await CleanupAsync();
    }
}

Antrean Latar Belakang Berbasis Kanal

Pola yang umum digunakan: layanan latar belakang membaca dari antrean Channel, sementara titik akhir HTTP memasukkan item pekerjaan ke antrean. Dengan demikian, penanganan permintaan terpisah dari pemrosesan pekerjaan.

public class BackgroundTaskQueue
{
    private readonly Channel<Func<CancellationToken, Task>> _queue
        = Channel.CreateBounded<Func<CancellationToken, Task>>(100);

    public ValueTask QueueAsync(Func<CancellationToken, Task> job)
        => _queue.Writer.WriteAsync(job);

    public IAsyncEnumerable<Func<CancellationToken, Task>> DequeueAllAsync(
        CancellationToken ct)
        => _queue.Reader.ReadAllAsync(ct);
}

// Register and use:
builder.Services.AddSingleton<BackgroundTaskQueue>();
builder.Services.AddHostedService<QueueProcessorService>();

Penanganan Kesalahan pada Layanan Latar Belakang

Pengecualian yang tidak ditangani dalam ExecuteAsync dapat menghentikan layanan secara diam-diam. Bungkus perulangan utama dalam try/catch dan catat kesalahan agar layanan tetap berjalan meskipun terjadi kegagalan individual.

protected override async Task ExecuteAsync(CancellationToken ct)
{
    while (!ct.IsCancellationRequested)
    {
        try
        {
            await ProcessNextBatchAsync(ct);
        }
        catch (OperationCanceledException) when (ct.IsCancellationRequested)
        {
            break; // normal shutdown
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Background processing error. Retrying in 5s.");
            await Task.Delay(5000, ct); // backoff before retry
        }
    }
}

StopAsync dan Batas Waktu Penghentian

Ganti StopAsync untuk melakukan pembersihan. Host meneruskan token penghentian — jika pembersihan memerlukan waktu lebih lama daripada batas waktu, proses akan dihentikan tanpa memedulikan hasilnya.

public override async Task StopAsync(CancellationToken stoppingToken)
{
    _logger.LogInformation("Service is stopping...");

    // Signal internal work to stop
    _internalCts.Cancel();

    // Wait for the Execute loop to complete (up to timeout)
    await base.StopAsync(stoppingToken);

    _logger.LogInformation("Service stopped");
}

// Increase the shutdown timeout if needed:
builder.Services.Configure<HostOptions>(opt =>
    opt.ShutdownTimeout = TimeSpan.FromSeconds(30));

Beberapa Layanan Latar Belakang

Daftarkan beberapa layanan yang di-host — semuanya berjalan secara bersamaan. Host memulainya sesuai urutan pendaftaran dan menghentikannya dalam urutan terbalik.

builder.Services.AddHostedService<DatabaseMigratorService>(); // startup task
builder.Services.AddHostedService<MetricsCollectorService>();  // continuous
builder.Services.AddHostedService<EmailNotificationService>(); // continuous
builder.Services.AddHostedService<CacheWarmupService>();       // startup task

// All run concurrently after app start
// Stopped in reverse registration order on shutdown

Dunia Nyata: Pekerja Pemrosesan Pesanan

Layanan latar belakang yang memproses pesanan tertunda dari antrean basis data, dengan pengaturan cakupan dan penanganan kesalahan yang tepat.

public class OrderProcessorService : BackgroundService
{
    private readonly IServiceScopeFactory _factory;
    private readonly ILogger<OrderProcessorService> _log;

    public OrderProcessorService(IServiceScopeFactory f, ILogger<OrderProcessorService> l)
    { _factory = f; _log = l; }

    protected override async Task ExecuteAsync(CancellationToken ct)
    {
        while (!ct.IsCancellationRequested)
        {
            try
            {
                using var scope = _factory.CreateScope();
                var processor = scope.ServiceProvider.GetRequiredService<IOrderProcessor>();
                int count = await processor.ProcessPendingAsync(ct);
                _log.LogInformation("Processed {Count} orders", count);
            }
            catch (Exception ex) when (!ct.IsCancellationRequested)
            {
                _log.LogError(ex, "Order processing failed");
            }
            await Task.Delay(TimeSpan.FromSeconds(10), ct);
        }
    }
}

Pemeriksaan Singkat

Mengapa layanan latar belakang harus menggunakan IServiceScopeFactory, bukan menyuntikkan DbContext secara langsung?

Ringkasan: IHostedService & BackgroundService

Inti pembelajaran:

  • IHostedService: StartAsync/StopAsync — untuk tugas mulai dan berhenti
  • BackgroundService: perulangan ExecuteAsync — untuk pekerjaan latar belakang yang berkelanjutan
  • Selalu gunakan IServiceScopeFactory untuk dependensi Scoped di dalam layanan latar belakang
  • Pantau token pembatalan pada setiap await agar penghentian dapat berlangsung secara bertahap
  • Bungkus isi perulangan dalam try/catch agar layanan tidak berhenti karena kesalahan
  • Gunakan HostOptions.ShutdownTimeout jika pembersihan memerlukan waktu lebih dari 5 detik
Gratis untuk memulai

Belajar C# dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
93
Pelajaran
346

Pertanyaan yang Sering Diajukan

Apakah pelajaran “IHostedService & BackgroundService” gratis?

Ya — teks lengkap “IHostedService & BackgroundService” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus C# Academy, upgrade ke CoddyKit PRO. Kursus C# Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “IHostedService & BackgroundService”?

Implementasikan IHostedService dan BackgroundService abstrak untuk menjalankan pekerjaan di latar belakang dalam host .NET. Kamu berlatih C# Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai C# Academy?

Tidak diperlukan pengalaman sebelumnya. C# Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.

Berapa lama pelajaran “IHostedService & BackgroundService” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran C# Academy ini?

Ya. Setiap pelajaran C# Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. IHostedService & BackgroundService
  2. Proyek Worker Service
  3. Tugas Berkala & Timer
  4. Pekerjaan Terjadwal Quartz.NET
← Kembali ke C# Academy