Running separate process in ASP.NET Core Web Minimal API

870 Views Asked by At

I have a long running process that I would like to add a REST api to. Through the API I would like to be able to inspect the values of variables inside the long running process.

I put together a proof of concept using minimal API:

public class Program
{
    public static int val = 0;
    public static object locker = new object();


    public static void Main(string[] args)
    {
        Task.Run(() =>
        {
            while (true)
            {
                lock (locker)
                {
                    val++;
                }
                Thread.Sleep(100);
            }
        });

        var builder = WebApplication.CreateBuilder(args);
        var app = builder.Build();

        app.MapGet("/", () => 
        {
            lock (locker)
                return val;
        });

        app.Run();
    }
}

My idea is to have the code for my long running process running inside of the Task.Run. Am I going about this the right way? Are there any potential pitfalls/gotchas to what Im trying to do?

1

There are 1 best solutions below

3
On

You could create a service that holds the state, and you can access that service from your API. A windows service/hosted service is great for a "long-running process", and it can host your API: documentation.

ValueService.cs

Implement BackgroundService for your long running process.

public class ValueService : BackgroundService
{
    private int _val;

    public int Value
    {
        get { return _val; }
        set { _val = value; }
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {        

        while (!stoppingToken.IsCancellationRequested)
        {
            await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
            Value++;
        }
    }
}

Program.cs

Register your service and register retrieval from the service provider.

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ValueService>();
builder.Services.AddHostedService(p => p.GetService<ValueService>()!);

var app = builder.Build();  
    

Inject service in your API:

app.MapGet("/", (ValueService valueService) =>
{
    return valueService.Value;       
});

app.Run();