Potrzebujesz rozwiązania do wykonywania zadań w tle w aplikacjach .NET? Hangfire to doskonałe narzędzie, które pozwala na łatwe harmonogramowanie i zarządzanie zadaniami asynchronicznymi. W tym poradniku przeprowadzę Cię przez proces integracji Hangfire z aplikacją ASP.NET Core 9, od konfiguracji po zaawansowane możliwości.
Czym jest Hangfire?
Hangfire to biblioteka open-source do zarządzania zadaniami w tle w aplikacjach .NET. Umożliwia definiowanie zadań, które mają być wykonywane asynchronicznie, bez blokowania głównego wątku aplikacji. Jest idealny do operacji takich jak:
- Wysyłanie e-maili
- Generowanie raportów
- Czyszczenie danych
- Przetwarzanie plików
- Cykliczne zadania utrzymaniowe
Konfiguracja projektu z Hangfire
Krok 1: Utworzenie projektu ASP.NET Core
- Utwórz nowy projekt typu Web API (szablon “ASP.NET Core Empty”)
- Nadaj mu nazwę (np. “HangfireDemo”)
Krok 2: Instalacja paczek NuGet
Następnie otwieramy projekt i instalujemy paczki NuGet:
Hangfire.AspNetCore
Hangfire.SqlServer
(jeśli używasz SQL Servera jako storage)Microsoft.Data.SqlClient
(jeśli używasz SQL Servera jako storage)
Teraz przechodzimy do pliku Program.cs
i konfigurujemy Hangfire.
Krok 3: Konfiguracja w Program.cs
W Program.cs
dodajemy konfigurację usług:
using Hangfire;
// Dodanie usług Hangfire
builder.Services.AddHangfire(config =>
config.UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireConnection")));
builder.Services.AddHangfireServer();
// Dodanie dashboardu do pipeline
app.UseHangfireDashboard();
Krok 4: Dodanie connection string w appsettings.json
"ConnectionStrings": {
"HangfireConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HangfireDB;Trusted_Connection=True;"
},
Krok 5: Utworzenie bazy danych
Możesz utworzyć bazę danych ręcznie lub użyć DatabaseInitializer (o tym później). Po uruchomieniu aplikacji panel Hangfire będzie dostępny pod adresem /hangfire
.
Możesz uruchomić aplikację
Możesz uruchomić aplikację i wpisać /hangfire, żeby zobaczyć dashboard.
Można tu sprawdzić:
- kolejkę zadań,
- zakończone, nieudane, błędy,
- retry,
- historię wykonania zadań.
- a także uruchomić lub usunąć zadania.
Typy zadań w Hangfire
1. Zadania jednorazowe (Fire-and-forget)
Zadania jednorazowe, które są uruchamiane natychmiast po zapisaniu ich w kolejce. Są wykonywane tylko raz, bez żadnych opóźnień czy cyklicznych powtórzeń. W przypadku zadania jednorazowego wystarczy skorzystać z metody Enqueue()
:
BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget job"));
Teraz zróbmy to samo korzystając z serwisu. Dodajemy klasę EmailService
:
// Definicja serwisu
public class EmailService
{
public void SendWelcomeEmail(string userEmail)
{
Console.WriteLine($"Wysłano powitalny email do: {userEmail}");
}
}
// Rejestracja serwisu
builder.Services.AddTransient<EmailService>();
// Wywołanie
BackgroundJob.Enqueue<EmailService>(service => service.SendWelcomeEmail("mariusz@dev-hobby.pl"));
2. Zadania opóźnione (Delayed jobs)
Zadania, które są uruchamiane po upływie określonego czasu lub o określonej dacie. Zadania opóźnione są rejestrowane za pomocą metody Schedule()
:
// Zadanie opóźnione o 5 minut
BackgroundJob.Schedule(() => Console.WriteLine("Delayed job"), TimeSpan.FromMinutes(5));
// Zadanie opoznione o 1 minute
BackgroundJob.Schedule<EmailService>(s => s.SendWelcomeEmail("scheduled@demo.pl"), TimeSpan.FromMinutes(1));
// Zadanie opóźnione na określoną datę
BackgroundJob.Schedule<EmailService>(service => service.SendWelcomeEmail("mariusz@dev-hobby.pl"), DateTimeOffset.Now.AddHours(1));
Jeśli zadanie jest zaplanowane, ale chcesz je anulować, możesz to zrobić w następujący sposób:
BackgroundJob.Delete(jobId);
3. Zadania cykliczne (Recurring jobs)
Zadania cykliczne, które są wykonywane zgodnie z harmonogramem, np. codziennie, co godzinę, itp. Zadania cykliczne można rejestrować za pomocą metody AddOrUpdate():
// Zadanie cykliczne – codziennie
RecurringJob.AddOrUpdate("dailyreport", () => Console.WriteLine("Recurring job"), Cron.Daily);
// Zadanie cykliczne z użyciem serwisu
RecurringJob.AddOrUpdate<EmailService>("daily-email", s => s.SendWelcomeEmail("daily@demo.pl"), Cron.Daily);
// Co godzinę
RecurringJob.AddOrUpdate("hourlyreport", () => Console.WriteLine("Hourly recurring job"), Cron.Hourly);
// Co tydzień w poniedziałek o 10:00
RecurringJob.AddOrUpdate("weeklyreport", () => Console.WriteLine("Weekly recurring job"), "0 10 * * 1");
Składni Cron:
Składnia Cron pozwala na precyzyjne określenie, kiedy zadanie ma być uruchomione:
- Minuty: 0-59
- Godziny: 0-23
- Dni miesiąca: 1-31
- Miesiące: 1-12
- Dni tygodnia: 0-6 (0 – niedziela)
Przykłady wyrażeń Cron:
Cron.Minutely
: Co minutę.Cron.Hourly
: Co godzinę.Cron.Daily
: Codziennie o północy.Cron.Weekly
: Co tydzień.
Zarządzanie zadaniami cyklicznymi z kodu i dashboardu:
Aktualizacja: Możesz zaktualizować zadanie cykliczne, używając AddOrUpdate()
Usuwanie: Aby usunąć zadanie cykliczne, użyj:
RecurringJob.RemoveIfExists("dailyreport");
4. Zadania kontynuacyjne (Continuations)
Zadania kontynuacyjne są uruchamiane po zakończeniu innych zadań. Można stworzyć łańcuch zadań, w którym jedno zadanie zależy od zakończenia poprzedniego. Aby zadanie kontynuacyjne zostało uruchomione po zakończeniu innego zadania, należy użyć metody ContinueJobWith()
:
var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("First job"));
BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine("Continuation job"));
Zaawansowane możliwości
Przypisywać zadania do określonych kolejek:
[Queue("emails")]
public void SendWelcomeEmail(string userEmail)
{
Console.WriteLine($"Wysłano powitalny email do: {userEmail}");
}
Konfiguracja ponownych prób (retry):
[AutomaticRetry(Attempts = 3)]
public void SendWelcomeEmail(string userEmail) {…}
Globalna konfiguracja Hangfire
builder.Services.AddHangfire(config => config.UseSqlServerStorage(builder.Configuration.GetConnectionString("HangfireConnection")).WithJobExpirationTimeout(TimeSpan.FromDays(7)); // Czas wygaśnięcia zadań
Hangfire.GlobalConfiguration.Configuration.UseFilter(new AutomaticRetryAttribute { Attempts = 3 }); // Liczba prób ponownych zadań
Domyślnie, w Hangfire, zadania nie mają ustawionej opcji ponownych prób. Oznacza to, że domyślnie, jeśli zadanie zakończy się błędem, Hangfire nie podejmie żadnej próby ponownego uruchomienia tego zadania. Bez tej opcji zadania nie będą powtarzane automatycznie po niepowodzeniu, chyba że skonfigurujesz to w taki sposób jak pokazałem.
Zabezpieczenie Dashboard
Aby dashboard nie był publicznie dostępny, możesz dodać prostą autoryzację:
1. Dodanie DashboardOptions
W dashboardzie Hangfire możemy zdefiniować uprawnienia do zarządzania zadaniami.
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new[] { new HangfireAuthorizationFilter() }
});
Gdzie MyAuthorizationFilter
to własna klasa implementująca IDashboardAuthorizationFilter
.
2 Konfiguracja uprawnień dostępu do dashboardu
Dodajemy filtr autoryzacji, który będzie kontrolował dostęp do panelu administracyjnego.
public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
// Przykład: dostęp tylko dla użytkowników administracyjnych
return context.GetHttpContext().User.IsInRole("Admin");
}
}
Automatyczne tworzenie bazy danych
Możesz zautomatyzować tworzenie bazy danych Hangfire:
public static class DatabaseInitializer
{
public static void EnsureHangfireDatabase(string connectionString)
{
var builder = new SqlConnectionStringBuilder(connectionString);
var databaseName = builder.InitialCatalog;
// Zmieniamy bazę docelową na 'master', by móc stworzyć nową
builder.InitialCatalog = "master";
using var connection = new SqlConnection(builder.ConnectionString);
connection.Open();
var commandText = $@"
IF NOT EXISTS (SELECT name FROM sys.databases WHERE name = N'{databaseName}')
BEGIN
CREATE DATABASE [{databaseName}]
END";
using var command = new SqlCommand(commandText, connection);
command.ExecuteNonQuery();
}
}
// Wykorzystanie w Program.cs
var connectionString = builder.Configuration.GetConnectionString("HangfireConnection");
DatabaseInitializer.EnsureHangfireDatabase(connectionString);
Podsumowanie
Hangfire to potężne narzędzie, które usprawnia zarządzanie zadaniami w tle w aplikacjach .NET:
- Fire-and-forget jobs: Do natychmiastowych, jednorazowych zadań
- Delayed jobs: Do wykonania po określonym czasie
- Recurring jobs: Do zadań cyklicznych zgodnie z harmonogramem
- Continuations: Do tworzenia złożonych workflow
Dzięki intuicyjnemu panelowi administracyjnemu możesz:
- Monitorować wszystkie zadania
- Sprawdzać historię wykonania
- Zarządzać zadaniami ręcznie
- Analizować błędy i próby ponownego wykonania
Pytania?
Czy korzystasz już z Hangfire w swoich projektach? Z jakimi wyzwaniami się spotkałeś? Podziel się swoimi doświadczeniami w komentarzach!
Jeśli ten tutorial był pomocny, subskrybuj mój kanał, aby otrzymywać powiadomienia o nowych materiałach dotyczących .NET i nie tylko.