IHostedService ja BackgroundService
Toteuttakaa IHostedService ja abstrakti BackgroundService suorittaaksenne taustatyötä .NET-isännän sisällä.
IHostedService ja BackgroundService on ilmainen C# Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu C# Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. C# Academy-kurssilla on yhteensä 4 oppituntia.
Mitä taustapalvelut ovat?
Taustapalvelut suorittavat pitkäkestoisia tehtäviä ASP.NET Core -sovelluksen rinnalla — ne voivat käsitellä jonoja, suorittaa ajastettuja tehtäviä tai valvoa resursseja. .NET tarjoaa kaksi vaihtoehtoa: IHostedService (minimaalinen) ja abstraktin BackgroundService-luokan (silmukoille sopiva).
IHostedService-rajapinta
IHostedService-rajapinnassa on kaksi metodia: StartAsync (kutsutaan hostin käynnistyessä) ja StopAsync (kutsutaan hallitun sammutuksen aikana). Se sopii erinomaisesti kertaluonteisiin käynnistys- ja sammutustehtäviin.
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: pitkäkestoiset silmukat
BackgroundService on abstrakti luokka, joka toteuttaa IHostedService-rajapinnan ja tarjoaa metodin ExecuteAsync(CancellationToken) — se suoritetaan sovelluksen koko elinkaaren ajan.
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>();Scoped-palveluiden käyttäminen
Taustapalvelut ovat Singleton-palveluita. Jos haluatte käyttää Scoped-palveluita, kuten DbContext-oliota, luokaa aina uusi scope jokaista työyksikköä varten IServiceScopeFactory-tehtaan avulla.
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);
}
}
}Hallittu sammutus
Kun host sammutetaan, se laukaisee peruutustunnisteen. ExecuteAsync-metodin tulee tarkkailla sitä ja suorittaa siivous. Host odottaa oletusarvoisesti enintään 5 sekuntia ennen pakotettua sammutusta.
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();
}
}Channel-pohjainen taustajono
Yleinen toimintamalli on, että taustapalvelu lukee tehtäviä Channel-jonosta samalla, kun HTTP-päätepisteet lisäävät siihen työyksiköitä. Näin pyyntöjen käsittely erotetaan työn suorittamisesta.
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>();Taustapalveluiden virheenkäsittely
ExecuteAsync-metodin käsittelemättömät poikkeukset voivat pysäyttää palvelun huomaamatta. Ympäröikää pääsilmukka try/catch-rakenteella ja kirjatkaa virheet lokiin, jotta palvelu pysyy käynnissä yksittäisistä virheistä huolimatta.
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 ja sammutuksen aikakatkaisu
Ohittakaa StopAsync siivouksen suorittamista varten. Host välittää sammutustunnisteen — jos siivous kestää aikakatkaisua pidempään, prosessi lopetetaan joka tapauksessa.
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));Useita taustapalveluita
Rekisteröikää useita hosted-palveluita — ne kaikki suoritetaan samanaikaisesti. Host käynnistää ne järjestyksessä ja pysäyttää ne käänteisessä järjestyksessä.
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 shutdownKäytännön esimerkki: tilausten käsittelijä
Taustapalvelu, joka käsittelee tietokantajonossa olevat tilaukset asianmukaisesti rajattuna ja virheet käsitellen.
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);
}
}
}Pikatarkistus
Miksi taustapalveluiden on käytettävä IServiceScopeFactorya sen sijaan, että DbContext injektoitaisiin suoraan?
Kertaus: IHostedService ja BackgroundService
Keskeiset opit:
IHostedService: StartAsync/StopAsync — käynnistys- ja sammutustehtäviinBackgroundService: ExecuteAsync-silmukka — jatkuvaan taustatyöhön- Käyttäkää aina
IServiceScopeFactory-tehdasta Scoped-riippuvuuksiin taustapalveluiden sisällä - Tarkkailkaa peruutustunnistetta jokaisessa await-kutsussa hallitun sammutuksen varmistamiseksi
- Ympäröikää silmukan runko try/catch-rakenteella, jotta virheet eivät pysäytä palvelua
- Käyttäkää
HostOptions.ShutdownTimeout-asetusta, jos siivous kestää yli 5 sekuntia
Opi C# tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 93
- Oppitunnit
- 346
Usein kysytyt kysymykset
Onko oppitunti ”IHostedService ja BackgroundService” ilmainen?
Kyllä – oppitunnin ”IHostedService ja BackgroundService” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko C# Academy-kurssin, päivitä CoddyKit PROhon. C# Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”IHostedService ja BackgroundService”?
Toteuttakaa IHostedService ja abstrakti BackgroundService suorittaaksenne taustatyötä .NET-isännän sisällä. Harjoittelet C# Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni C# Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin C# Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.
Kuinka kauan ”IHostedService ja BackgroundService”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä C# Academy-oppitunnilla?
Kyllä. Jokainen C# Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- IHostedService ja BackgroundService
- Worker Service -projektit
- Toistuvat tehtävät ja ajastimet
- Quartz.NET-ajastetut työt