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
<PackageReference Include="Josupeit.Practices.Services" Version="1.0.7" />
<PackageVersion Include="Josupeit.Practices.Services" Version="1.0.7" />
<PackageReference Include="Josupeit.Practices.Services" />
paket add Josupeit.Practices.Services --version 1.0.7
#r "nuget: Josupeit.Practices.Services, 1.0.7"
#:package Josupeit.Practices.Services@1.0.7
#addin nuget:?package=Josupeit.Practices.Services&version=1.0.7
#tool nuget:?package=Josupeit.Practices.Services&version=1.0.7
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 | Versions 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. |
-
.NETStandard 2.0
- Josupeit.Practices.Services.Abstractions (>= 1.0.0 && < 2.0.0)
-
.NETStandard 2.1
- Josupeit.Practices.Services.Abstractions (>= 1.0.0 && < 2.0.0)
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 |