Last active
January 30, 2020 13:35
-
-
Save solrevdev/f28ab81363e9875d25b3f3453339a556 to your computer and use it in GitHub Desktop.
.NET Timer with CancellationToken support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Logging": { | |
"LogLevel": { | |
"Default": "Information", | |
"Microsoft": "Warning", | |
"Microsoft.Hosting.Lifetime": "Information" | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Logging": { | |
"LogLevel": { | |
"Default": "Information", | |
"Microsoft": "Warning", | |
"Microsoft.Hosting.Lifetime": "Information" | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Hosting; | |
namespace tempy | |
{ | |
public static class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
CreateHostBuilder(args).Build().Run(); | |
} | |
public static IHostBuilder CreateHostBuilder(string[] args) => | |
Host.CreateDefaultBuilder(args) | |
.ConfigureServices((_, services) => services.AddHostedService<Worker>()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk.Worker"> | |
<PropertyGroup> | |
<TargetFramework>netcoreapp3.1</TargetFramework> | |
<UserSecretsId>dotnet-tempy-2E552B51-4FEB-4B21-9AFC-4E4C7A69F645</UserSecretsId> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.1" /> | |
</ItemGroup> | |
</Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Microsoft.Extensions.DependencyInjection; | |
using Microsoft.Extensions.Hosting; | |
using Microsoft.Extensions.Logging; | |
namespace tempy | |
{ | |
/// <summary> | |
/// Thanks to this post https://stackoverflow.com/a/56666084/2041 | |
/// </summary> | |
public class Worker : BackgroundService | |
{ | |
private readonly ILogger<Worker> _logger; | |
private Timer _timer; | |
private Task _executingTask; | |
private readonly CancellationTokenSource _stoppingCts = new CancellationTokenSource(); | |
public Worker(ILogger<Worker> logger) | |
{ | |
_logger = logger; | |
} | |
public override Task StartAsync(CancellationToken stoppingToken) | |
{ | |
_logger.LogInformation("Worker started at: {time}", DateTimeOffset.Now); | |
_timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5)); | |
return Task.CompletedTask; | |
} | |
public override async Task StopAsync(CancellationToken stoppingToken) | |
{ | |
_timer?.Change(Timeout.Infinite, 0); | |
if (_executingTask == null) | |
{ | |
await Task.CompletedTask.ConfigureAwait(false); | |
} | |
try | |
{ | |
_logger.LogInformation("Worker stopping at: {time}", DateTimeOffset.Now); | |
_stoppingCts.Cancel(); | |
} | |
finally | |
{ | |
await Task.WhenAny(_executingTask, Task.Delay(Timeout.Infinite, stoppingToken)).ConfigureAwait(false); | |
} | |
await Task.CompletedTask.ConfigureAwait(false); | |
} | |
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | |
{ | |
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); | |
await Task.CompletedTask.ConfigureAwait(false); | |
} | |
public override void Dispose() | |
{ | |
_timer?.Dispose(); | |
base.Dispose(); | |
} | |
private void DoWork(object state) | |
{ | |
GC.KeepAlive(_timer); | |
_timer?.Change(Timeout.Infinite, 0); | |
_executingTask = DoWorkAsync(_stoppingCts.Token); | |
} | |
private async Task DoWorkAsync(CancellationToken stoppingToken) | |
{ | |
if (!stoppingToken.IsCancellationRequested) | |
{ | |
_logger.LogInformation("Worker starting DoWorkAsync at: {time}", DateTimeOffset.Now); | |
Thread.Sleep(5000); | |
_logger.LogInformation("Worker completed DoWorkAsync at: {time}", DateTimeOffset.Now); | |
_timer.Change(TimeSpan.FromSeconds(5), TimeSpan.FromMilliseconds(-1)); | |
await Task.CompletedTask.ConfigureAwait(false); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment