, , .
, , , 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
{
private readonly Lazy<Task> _executingTask;
private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource();
public StartupJobService(Func<TJob> factory)
{
_executingTask = new Lazy<Task>(() => factory().ExecuteAsync(_stoppingCts.Token));
}
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)
{
services.AddTransient<TJob, TJob>();
services.AddSingleton<Func<TJob>>(cont =>
{
return () => cont.GetService<TJob>();
});
services.AddSingleton<IHostedService, StartupJobService<TJob>>();
}
}