Async.Task.Runner.Core
1.0.1
dotnet add package Async.Task.Runner.Core --version 1.0.1
NuGet\Install-Package Async.Task.Runner.Core -Version 1.0.1
<PackageReference Include="Async.Task.Runner.Core" Version="1.0.1" />
<PackageVersion Include="Async.Task.Runner.Core" Version="1.0.1" />
<PackageReference Include="Async.Task.Runner.Core" />
paket add Async.Task.Runner.Core --version 1.0.1
#r "nuget: Async.Task.Runner.Core, 1.0.1"
#:package Async.Task.Runner.Core@1.0.1
#addin nuget:?package=Async.Task.Runner.Core&version=1.0.1
#tool nuget:?package=Async.Task.Runner.Core&version=1.0.1
β±οΈ Async Task Runner (Generic In-Memory Background Tasks)
A lightweight, generic utility for running long-running or non-blocking tasks in-memory with parallel execution, enabling you to build high-performance APIs by offloading independent tasks without waiting for their completion upfront.
π Use Case
This library is designed to solve a common problem in API design:
β "What if I have a long-running task that I donβt immediately need the result for, but I will later in the same request or another part of the workflow?"
Instead of awaiting the result right away, you can:
- Kick off the task early using
StartTaskAsync(...)
and get a uniqueTaskId
. - Let the task run in the background, independently.
- Later (when the result is actually needed), call
GetTaskResultByTaskIdAsync(...)
to wait for completion if necessary and retrieve the result.
This allows multiple operations to proceed in parallel, reducing overall response time and improving throughput for your APIs.
π§ Key Features
- β
Generic task result support (
T
) - β In-memory result caching with 1-minute expiration
- β
Thread-safe design with
ConcurrentDictionary
andIMemoryCache
- β Easily pluggable via Dependency Injection in ASP.NET Core
- β No external dependencies β 100% .NET built-in
Installation
Install the package via NuGet:
dotnet add package Async.Task.Runner.Core
using Async.Task.Runner.Core.Extensions;
var builder = WebApplication.CreateBuilder(args);
builder.Services.ConfigureTaskRunnerServices();
π‘ Example Use Case: Geo Lookup in the Background
Let's say you have an external geo service (IGeoService
) that takes a latitude and longitude and returns geographic information (like country, city, village).
This call might take a couple of seconds, and you only need the result at the end of your API logic, not right away.
public interface IGeoService
{
Task<LocationInfo> GetLocationAsync(double latitude, double longitude);
}
public class GeoService : IGeoService
{
public async Task<LocationInfo> GetLocationAsync(double latitude, double longitude)
{
//simulate long running task
await System.Threading.Tasks.Task.Delay(1500);
return new LocationInfo { CountryId = 100, CityId = 101, VillageId = 1011 };
}
}
public class LocationInfo
{
public long CountryId { get; set; }
public long CityId { get; set; }
public long VillageId { get; set; }
}
You can offload it like this:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController(ILogger<WeatherForecastController> logger) : ControllerBase
{
private static readonly string[] Summaries =
[
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
];
//simulate current location
private static readonly double Latitude = (double)35.72828545564619;
private static readonly double Longitude = (double)51.41550287298716;
[HttpGet]
[Route("GetWeatherForecast/normal")]
public async Task<IEnumerable<WeatherForecast>> GetNormal([FromServices] IGeoService geoService)
{
await System.Threading.Tasks.Task.Delay(1000);
var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
var locationInfo = await geoService.GetLocationAsync(Latitude, Longitude);
foreach (var weatherForecast in result)
{
weatherForecast.CountryId = locationInfo.CountryId;
}
return result; //in 2.5 seconds
}
[HttpGet]
[Route("GetWeatherForecast/with-task-runner-usage")]
public async Task<IEnumerable<WeatherForecast>> GetWithTaskRunner([FromServices] IGeoService geoService,
[FromServices] IAsyncTaskRunner<LocationInfo> locationFinderTaskRunner)
{
var taskId = await locationFinderTaskRunner.StartTaskAsync(async () =>
await geoService.GetLocationAsync(Latitude, Longitude));
await System.Threading.Tasks.Task.Delay(1000);
var result = Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
var locationInfo = await locationFinderTaskRunner.GetTaskResultByTaskIdAsync(taskId);
foreach (var weatherForecast in result)
{
weatherForecast.CountryId = locationInfo.CountryId;
}
return result; //in 1.5 seconds
}
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | 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 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. |
-
net8.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.
Initial release.