Short-term background task in .NET Core

I just opened a class IHostedServiceand .NET Core 2.1 BackgroundService. I think the idea is awesome. Documentation .

All the examples I found are used for lengthy tasks (until the application dies). But I need this for a short time. What is the right way to do this?

For example:
I want to execute several requests (they will take about 10 seconds) after the application starts. And only in development mode. I do not want to delay the launch of the application, so IHostedServiceit seems like a good approach. I cannot use Task.Factory.StartNewbecause I need dependency injection.

I am currently doing this:

public class UpdateTranslatesBackgroundService: BackgroundService
{
    private readonly MyService _service;

    public UpdateTranslatesBackgroundService(MyService service)
    {
        //MService injects DbContext, IConfiguration, IMemoryCache, ...
        this._service = service;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        await ...
    }
}

launch:

public static IServiceProvider Build(IServiceCollection services, ...)
{
    //.....
    if (hostingEnvironment.IsDevelopment())
        services.AddSingleton<IHostedService, UpdateTranslatesBackgroundService>();
    //.....
}

. ? singleton ( , ). . , , . .

+4
2

, , . , , , async!= Multithreaded. , BackgroundService "", . , . , sql- async-, -

public class StopStartupService : BackgroundService
    {
        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            System.Threading.Thread.Sleep(1000);
            return Task.CompletedTask;
        }
    }

.

, .

?

Task.Run ( Task.Factory.StartNew, , ) , , . , , , . , , , , , Task.Run , , - .

#?

( XAML ). , , , , , . , - , . , , , . , BackgroundService , .

?

, , , , . , , .

- , , .

   public interface IStartupJob
    {
        Task ExecuteAsync(CancellationToken stoppingToken);
    }

    public class DBJob : IStartupJob
    {
        public Task ExecuteAsync(CancellationToken stoppingToken)
        {
            return Task.Run(() => System.Threading.Thread.Sleep(10000));
        }
    }

    public class StartupJobService<TJob> : IHostedService, IDisposable where TJob: class,IStartupJob
    {
        //This ensures a single start of the task this is important on a singletone
        private readonly Lazy<Task> _executingTask;

        private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();

        public StartupJobService(Func<TJob> factory)
        {
            //In order for the transient item to be in memory as long as it is needed not to be in memory for the lifetime of the singleton I use a simple factory
            _executingTask = new Lazy<Task>(() => factory().ExecuteAsync(_stoppingCts.Token));
        }

        //You can use this to tell if the job is done
        public virtual Task Done => _executingTask.IsValueCreated ? _executingTask.Value : throw new Exception("BackgroundService not started");

        public virtual Task StartAsync(CancellationToken cancellationToken)
        {

            if (_executingTask.Value.IsCompleted)
            {
                return _executingTask.Value;
            }

            return Task.CompletedTask;
        }

        public virtual async Task StopAsync(CancellationToken cancellationToken)
        {
            if (_executingTask == null)
            {
                return;
            }

            try
            {
                _stoppingCts.Cancel();
            }
            finally
            {
                await Task.WhenAny(_executingTask.Value, Task.Delay(Timeout.Infinite,
                                                              cancellationToken));
            }

        }

        public virtual void Dispose()
        {
            _stoppingCts.Cancel();
        }

        public static void AddService(IServiceCollection services)
        {
            //Helper to register the job
            services.AddTransient<TJob, TJob>();

            services.AddSingleton<Func<TJob>>(cont => 
            {
                return () => cont.GetService<TJob>();
            });

            services.AddSingleton<IHostedService, StartupJobService<TJob>>();
        }
    }
+4

Communist.StartupTasks, . Nuget.

.NET Core App. .

, (.. ).

0

Source: https://habr.com/ru/post/1692361/


All Articles