Bagikan melalui


IHostedService Menerapkan antarmuka

Ketika Anda membutuhkan kontrol terbatas di luar yang disediakan BackgroundService, Anda dapat menerapkan sendiri IHostedService. Antarmuka IHostedService adalah dasar untuk semua layanan yang berjalan lama di .NET. Implementasi kustom didaftarkan dengan menggunakan metode ekstensi AddHostedService<THostedService>(IServiceCollection).

Dalam tutorial ini, Anda akan belajar cara:

  • Terapkan antarmuka IHostedService dan IAsyncDisposable.
  • Buat layanan berbasis timer.
  • Daftarkan implementasi kustom dengan injeksi dependensi dan pencatatan log.

Petunjuk / Saran

Semua kode sumber contoh "Pekerja di .NET" tersedia di Browser Sampel untuk diunduh. Untuk informasi selengkapnya, lihat Menelusuri sampel kode: Pekerja di .NET.

Prasyarat

Membuat proyek baru

Untuk membuat proyek Layanan Pekerja baru dengan Visual Studio, Anda akan memilih File>Baru>Proyek.... Dari dialog Buat proyek baru mencari "Layanan Pekerja", dan pilih templat "Layanan Pekerja". Jika Anda lebih suka menggunakan .NET CLI, buka terminal favorit Anda di direktori kerja. Jalankan perintah dotnet new, dan ganti <Project.Name> dengan nama proyek yang Anda inginkan.

dotnet new worker --name <Project.Name>

Untuk informasi selengkapnya tentang perintah proyek layanan worker baru .NET CLI, lihat dotnet new worker.

Petunjuk / Saran

Jika Anda menggunakan Visual Studio Code, Anda dapat menjalankan perintah .NET CLI dari terminal terintegrasi. Untuk informasi selengkapnya, lihat Visual Studio Code: Terminal Terintegrasi.

Membuat layanan timer

Layanan latar belakang berbasis timer menggunakan System.Threading.Timer kelas . Timer memicu metode DoWork. Timer dinonaktifkan dan IHostLifetime.StopAsync(CancellationToken) dibuang ketika kontainer layanan dibuang pada IAsyncDisposable.DisposeAsync():

Ganti konten Worker dari templat dengan kode C# berikut, dan ganti nama file menjadi TimerService.cs:

namespace App.TimerHostedService;

public sealed class TimerService(ILogger<TimerService> logger) : IHostedService, IAsyncDisposable
{
    private readonly Task _completedTask = Task.CompletedTask;
    private int _executionCount = 0;
    private Timer? _timer;

    public Task StartAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation("{Service} is running.", nameof(TimerHostedService));
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

        return _completedTask;
    }

    private void DoWork(object? state)
    {
        int count = Interlocked.Increment(ref _executionCount);

        logger.LogInformation(
            "{Service} is working, execution count: {Count:#,0}",
            nameof(TimerHostedService),
            count);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Service} is stopping.", nameof(TimerHostedService));

        _timer?.Change(Timeout.Infinite, 0);

        return _completedTask;
    }

    public async ValueTask DisposeAsync()
    {
        if (_timer is IAsyncDisposable timer)
        {
            await timer.DisposeAsync();
        }

        _timer = null;
    }
}

Penting

Worker itu adalah subkelas dari BackgroundService. Sekarang, TimerService mengimplementasi antarmuka IHostedService dan IAsyncDisposable.

TimerService adalah sealed, dan mengkaskade panggilan DisposeAsync dari instansnya _timer. Untuk informasi selengkapnya tentang "pola dispose bertingkat", lihat Menerapkan DisposeAsync metode.

Ketika StartAsync dipanggil, timer diinisialisasi, sehingga memulai penghitungan waktu.

Petunjuk / Saran

Timer Tidak menunggu eksekusi DoWork sebelumnya selesai, sehingga pendekatan yang ditampilkan mungkin tidak cocok untuk setiap skenario. Interlocked.Increment digunakan untuk menaikkan penghitung eksekusi sebagai operasi atomik, yang memastikan bahwa beberapa utas tidak melakukan pembaruan _executionCount secara bersamaan.

Ganti konten yang ada Program dengan kode C# berikut:

using App.TimerHostedService;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<TimerService>();

IHost host = builder.Build();
host.Run();

Layanan ini terdaftar di (Program.cs) dengan AddHostedService metode ekstensi. Ini adalah metode ekstensi yang sama dengan yang Anda gunakan saat mendaftarkan BackgroundService subkelas, karena keduanya mengimplementasikan IHostedService antarmuka.

Untuk informasi selengkapnya tentang mendaftarkan layanan, lihat Injeksi Dependensi di .NET.

Memverifikasi fungsionalitas layanan

Untuk menjalankan aplikasi dari Visual Studio, pilih F5 atau pilih opsi menu Debug>Mulai Debugging . Jika Anda menggunakan .NET CLI, jalankan dotnet run perintah dari direktori kerja:

dotnet run

Untuk informasi selengkapnya tentang perintah jalankan .NET CLI, lihat dotnet run.

Biarkan aplikasi berjalan sedikit untuk menghasilkan beberapa kenaikan jumlah eksekusi. Anda akan melihat output yang mirip dengan yang berikut ini:

info: App.TimerHostedService.TimerService[0]
      TimerHostedService is running.
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\timer-service
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 1
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 2
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 3
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 4
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is stopping.

Jika menjalankan aplikasi dari dalam Visual Studio, pilih Debug>Hentikan Penelusuran Kesalahan.... Atau, pilih Ctrl + C dari jendela konsol untuk memberi sinyal pembatalan.

Lihat juga

Ada beberapa tutorial terkait yang perlu dipertimbangkan: