Josupeit.Practices.Services 1.0.7

Prefix Reserved
dotnet add package Josupeit.Practices.Services --version 1.0.7
                    
NuGet\Install-Package Josupeit.Practices.Services -Version 1.0.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Josupeit.Practices.Services" Version="1.0.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Josupeit.Practices.Services" Version="1.0.7" />
                    
Directory.Packages.props
<PackageReference Include="Josupeit.Practices.Services" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Josupeit.Practices.Services --version 1.0.7
                    
#r "nuget: Josupeit.Practices.Services, 1.0.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Josupeit.Practices.Services@1.0.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Josupeit.Practices.Services&version=1.0.7
                    
Install as a Cake Addin
#tool nuget:?package=Josupeit.Practices.Services&version=1.0.7
                    
Install as a Cake Tool

Josupeit.Practices.Services

Managing a service lifecycle correctly is surprisingly subtle. State transitions need to be valid (you cannot resume a service that was never paused), thread safety matters, and disposal has to be coordinated with the running state. This package provides abstract base classes that handle all of that bookkeeping, leaving you to focus on what the service actually does.

dotnet add package Josupeit.Practices.Services

How to implement a service

Synchronous service

Inherit from Service and implement the two abstract lifecycle hooks. The base class manages the State property and validates transitions — if you call Start() on an already-running service, it throws an InvalidOperationException rather than silently misbehaving.

public sealed class DataSyncService : Service
{
    private Timer? _timer;

    protected override void OnStart()
    {
        _timer = new Timer(_ => Synchronize(), null, TimeSpan.Zero, TimeSpan.FromMinutes(1));
    }

    protected override void OnStop()
    {
        _timer?.Dispose();
        _timer = null;
    }
}

var svc = new DataSyncService();
svc.Start();
Console.WriteLine(svc.State); // Running
svc.Stop();

Adding pause support

Pausing is opt-in. Override CanPause to return true, then override the two pause hooks.

public sealed class ThrottledSyncService : Service
{
    public override bool CanPause => true;

    protected override void OnStart()  { /* start work */ }
    protected override void OnStop()   { /* stop work  */ }
    protected override void OnPause()  { /* stop processing new items */ }
    protected override void OnResume() { /* resume processing         */ }
}

Asynchronous service

When the lifecycle itself involves asynchronous operations — for example, flushing a queue before stopping — inherit from AsyncService instead. The hooks receive a CancellationToken that callers can use to abort a long-running transition.

public sealed class BackgroundProcessor : AsyncService
{
    protected override async Task OnStartAsync(CancellationToken cancellationToken)
    {
        await InitializeAsync(cancellationToken);
    }

    protected override async Task OnStopAsync(CancellationToken cancellationToken)
    {
        await FlushAsync(cancellationToken);
    }
}

var worker = new BackgroundProcessor();
await worker.StartAsync(cancellationToken);
await worker.StopAsync(cancellationToken);

Service with disposal

When the service owns resources that must be released, choose a base class that also implements IDisposable or IAsyncDisposable. Override the resource cleanup methods to release what the service owns.

public sealed class ResourceService : DisposableService
{
    private readonly Stream _stream = File.OpenRead("data.bin");

    protected override void OnStart() { /* ... */ }
    protected override void OnStop()  { /* ... */ }

    protected override void DisposeManagedResources() => _stream.Dispose();
}

Available base classes

Base class Lifecycle Disposal
Service Sync
DisposableService Sync IDisposable
AsyncDisposableService Sync IDisposable + IAsyncDisposable
AsyncService Async
DisposableAsyncService Async IDisposable
AsyncDisposableAsyncService Async IDisposable + IAsyncDisposable

The interfaces that these classes implement live in Josupeit.Practices.Services.Abstractions, which is pulled in automatically as a transitive dependency.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Josupeit.Practices.Services:

Package Downloads
Josupeit.Practices.Schedulers.Core

Abstract base classes for building custom IScheduler implementations. Reduces the full IScheduler API to a single Enqueue or EnqueueAsync override with all sync/async bridging handled.

Josupeit.Practices.Schedulers.Channel

Channel-backed IScheduler with FIFO ordering, configurable parallelism, back-pressure, and pause/resume support. Built on System.Threading.Channels.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.7 234 3/10/2026