BackgroundTaskQueue.AspNetCore 2.0.1

dotnet add package BackgroundTaskQueue.AspNetCore --version 2.0.1
                    
NuGet\Install-Package BackgroundTaskQueue.AspNetCore -Version 2.0.1
                    
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="BackgroundTaskQueue.AspNetCore" Version="2.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BackgroundTaskQueue.AspNetCore" Version="2.0.1" />
                    
Directory.Packages.props
<PackageReference Include="BackgroundTaskQueue.AspNetCore" />
                    
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 BackgroundTaskQueue.AspNetCore --version 2.0.1
                    
#r "nuget: BackgroundTaskQueue.AspNetCore, 2.0.1"
                    
#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 BackgroundTaskQueue.AspNetCore@2.0.1
                    
#: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=BackgroundTaskQueue.AspNetCore&version=2.0.1
                    
Install as a Cake Addin
#tool nuget:?package=BackgroundTaskQueue.AspNetCore&version=2.0.1
                    
Install as a Cake Tool

BackgroundTaskQueue.AspNetCore

NuGet Version

A simple and scalable way to queue fire-and-forget background work in ASP.NET Core using dependency injection, scoped lifetimes, and category-based parallelism.

This service enables background work execution without requiring hosted services in your own code, while supporting graceful shutdown, cancellation, and error handling.

Features

  • Scoped dependency injection for background tasks
  • Optional named categories with configurable concurrency and queueing
  • Bounded capacity with task rejection
  • Graceful cancellation on shutdown
  • Customizable exception logging via IOffloadWorkExceptionLogger
  • Agressive unit testing

Installation

Register the service with default configuration:

// Defaults to a MaxDegreeOfParallelism of 3, unbounded capacity
builder.Services.AddOffloadWorkService();

Or customize the default configuration:

builder.Services.AddOffloadWorkService((OffloadWorkServiceOptions opt) =>
{
    // Controls how many tasks can run concurrently
    opt.MaxDegreeOfParallelism = 5;
    // Limits the number of active tasks (-1 for unlimited)
    opt.BoundedCapacity = 100;
});

Or define multiple named categories:

builder.Services.AddOffloadWorkService((OffloadWorkServiceCategoryOptions cat) =>
{
    cat.AddCategory("email", new OffloadWorkServiceOptions
    {
        MaxDegreeOfParallelism = 2,
        BoundedCapacity = 10
    });

    cat.AddCategory("pdf", new OffloadWorkServiceOptions
    {
        MaxDegreeOfParallelism = 4,
        BoundedCapacity = -1 // unbounded
    });
});

Usage

Inject IOffloadWorkService into your controller or service.

public sealed class MyController: ControllerBase
{
    private readonly IOffloadWorkService _offloader;

    public MyController(IOffloadWorkService offloadWorkService)
    {
        _offloader = offloadWorkService;
    }
}

Offload to the default category:

[HttpPost, Route("reindex")]
public IActionResult Reindex()
{
    var accepted = _offloader.Offload(async (sp, _, ct) =>
    {
        var search = sp.GetRequiredService<ISearchIndexer>();
        await search.ReindexAsync(ct);
    }, param: default);

    return accepted ? Accepted() :
        StatusCode(StatusCodes.Status429TooManyRequests, "Queue full");
}

Offload to a named category:

[HttpPost, Route("send-email")]
public IActionResult SendEmail([FromBody] EmailRequest request)
{
    var accepted = _offloader.Offload("email", async (sp, data, ct) =>
    {
        var sender = sp.GetRequiredService<IEmailSender>();
        await sender.SendAsync(data.To, data.Subject, data.Body, ct);
    }, request);

    return accepted ? Accepted() :
        StatusCode(StatusCodes.Status429TooManyRequests, "Email queue full");
}

Checking Queue Length

You can also retrieve the current length of the task queue for monitoring or logging purposes:

var queueLength = _offloader.GetActiveCount();
var queueLengthEmail = _offloader.GetActiveCount("email");

Custom Exception Logging

Implement a custom logger to capture exceptions from background tasks.

public sealed class MyExceptionLogger : IOffloadWorkExceptionLogger
{
    public void Log(Exception ex, string? category)
    {
        // Send to telemetry, logger, etc.
    }
}

Register it:

builder.Services.AddTransient<IOffloadWorkExceptionLogger, MyExceptionLogger>();

If registered, it will be used in place of the default ILogger<OffloadWorkService> for exceptions.

Behavior

  • BoundedCapacity is total active + queued items
  • Offload returns false if the queue is full
  • Background tasks receive a scoped IServiceProvider
  • Cancellation tokens are honored during shutdown
  • Logging is customizable but falls back to ILogger if needed

Clean Shutdown

The service cancels all running and queued tasks during shutdown using linked cancellation tokens. Resources are disposed automatically.

Contributing

Contributions are welcome! If you have improvements or bug fixes, please open an issue or submit a pull request.

License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  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 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.1 204 3/23/2025
2.0.0 157 3/23/2025
1.0.0 150 3/17/2025