Worker Services, Windows Services and Scheduling

Install: sc.exe create "Shop Inbox" binPath= "C:\Svc\Shop.Worker.exe", or PowerShell New-Service. On Linux: systemd (UseSystemd()).

Scheduling: PeriodicTimer, Quartz.NET (cron triggers), Hangfire (persistent jobs + dashboard; the dashboard needs an ASP.NET Core host), Windows Task Scheduler + console app.

Graceful shutdown: honor stoppingToken, set HostOptions.ShutdownTimeout.

Public Class InboxWorker
    Inherits BackgroundService
    Private ReadOnly _logger As ILogger(Of InboxWorker)
    Private ReadOnly _scopeFactory As IServiceScopeFactory
    Public Sub New(logger As ILogger(Of InboxWorker), scopeFactory As IServiceScopeFactory)
        _logger = logger : _scopeFactory = scopeFactory
    End Sub

    Protected Overrides Async Function ExecuteAsync(stoppingToken As Threading.CancellationToken) As Task
        Using timer As New Threading.PeriodicTimer(TimeSpan.FromMinutes(5))
            Do
                Try
                    Using scope = _scopeFactory.CreateScope()
                        Dim processor = scope.ServiceProvider.GetRequiredService(Of IInboxProcessor)()
                        Await processor.ProcessAsync(stoppingToken)
                    End Using
                Catch ex As Exception When Not TypeOf ex Is OperationCanceledException
                    _logger.LogError(ex, "Inbox processing failed")
                End Try
            Loop While Await timer.WaitForNextTickAsync(stoppingToken)
        End Using
    End Function
End Class

' Program: builder.Services.AddHostedService(Of InboxWorker)() ; builder.Services.AddWindows
…