Skip to content

Commit c614caf

Browse files
committedMar 18, 2025
Simplify cancellation token creation and handling
Since a CancellationTokenSource was needed that provides a possibility to create an event handler to register at the Console.CancelKeyPress event, the not really factory like CancellationTokenFactory class was renamed into ConsoleCancellationTokenSource and inherited instead from CancellationTokenSource. By then duplicated and obsolete code was removed and the already existing event handler creation method was renamed. So, now this class purpose and behavior should be more clear.
1 parent 97b4f55 commit c614caf

File tree

3 files changed

+20
-29
lines changed

3 files changed

+20
-29
lines changed
 

‎src/ConnyConsole/App.cs

+7-7
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@ namespace ConnyConsole;
88
public class App
99
{
1010
private readonly AppSettings _appSettings;
11-
private readonly CancellationTokenFactory _cancellationTokenFactory;
11+
private readonly ConsoleCancellationTokenSource _consoleCancellationTokenSource;
1212
private readonly ILogger<App> _logger;
1313

14-
public App(IOptions<AppSettings> appSettings, CancellationTokenFactory cancellationTokenFactory, ILogger<App> logger)
14+
public App(IOptions<AppSettings> appSettings, ConsoleCancellationTokenSource consoleCancellationTokenSource, ILogger<App> logger)
1515
{
1616
_appSettings = appSettings.Value;
17-
_cancellationTokenFactory = cancellationTokenFactory;
17+
_consoleCancellationTokenSource = consoleCancellationTokenSource;
1818
_logger = logger;
1919

20-
RegisterCancellation();
20+
RegisterConsoleCancellation();
2121
}
2222

2323
public Task<int> RunAsync()
2424
{
25-
while (!_cancellationTokenFactory.CancellationToken.IsCancellationRequested)
25+
while (!_consoleCancellationTokenSource.Token.IsCancellationRequested)
2626
{
2727
_logger.LogInformation("I'm working every {LoopOutputInterval} seconds...",
2828
_appSettings.LoopOutputInterval.TotalSeconds);
@@ -36,9 +36,9 @@ public Task<int> RunAsync()
3636
return Task.FromResult(0);
3737
}
3838

39-
private void RegisterCancellation()
39+
private void RegisterConsoleCancellation()
4040
{
4141
Console.CancelKeyPress +=
42-
_cancellationTokenFactory.CreateHandler(_appSettings.CancellationTimeout);
42+
_consoleCancellationTokenSource.CreateCancellationHandler(_appSettings.CancellationTimeout);
4343
}
4444
}

‎src/ConnyConsole/Extensions/ServiceCollectionExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public static IServiceCollection AddConfiguration(this IServiceCollection servic
1717

1818
services.Configure<AppSettings>(hostContext.Configuration.GetSection(AppSettings.SectionName));
1919

20-
services.AddTransient<CancellationTokenFactory>();
20+
services.AddTransient<ConsoleCancellationTokenSource>();
2121
services.AddTransient<App>();
2222

2323
return services;

‎src/ConnyConsole/Infrastructure/CancellationTokenFactory.cs ‎src/ConnyConsole/Infrastructure/ConsoleCancellationTokenSource.cs

+12-21
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,33 @@
1-
// This class function is based on https://medium.com/@sawyer.watts/a-beginners-guide-to-net-s-hostbuilder-part-2-cancellation-857ae3e6ff02
2-
3-
using Microsoft.Extensions.Logging;
1+
using Microsoft.Extensions.Logging;
42

53
namespace ConnyConsole.Infrastructure;
64

7-
public sealed class CancellationTokenFactory(ILogger<CancellationTokenFactory> logger) : IDisposable
5+
/// <inheritdoc/>
6+
public sealed class ConsoleCancellationTokenSource(ILogger<ConsoleCancellationTokenSource> logger)
7+
: CancellationTokenSource
88
{
9-
private bool _gracefulCancel = true;
10-
private readonly CancellationTokenSource _cancellationTokenSource = new();
11-
12-
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
13-
14-
/// <summary>
15-
/// Releases the resources used by this <see cref="CancellationTokenSource"/>
16-
/// </summary>
17-
/// <remarks>
18-
/// This method is not thread-safe for any other concurrent calls.
19-
/// </remarks>
20-
public void Dispose() => _cancellationTokenSource.Dispose();
9+
private bool _isGracefulCancelled = true;
2110

2211
/// <summary>
2312
/// Creates a <see cref="ConsoleCancelEventHandler"/> for a gracefully (first Ctrl+C) or forced (second Ctrl+C) application exit.
2413
/// It can be registered on the <see cref="Console.CancelKeyPress"/> event.
2514
/// </summary>
2615
/// <param name="timeout">The timeout after which the app is forcibly terminated.</param>
2716
/// <returns>The configured <see cref="ConsoleCancelEventHandler"/> event.</returns>
28-
public ConsoleCancelEventHandler CreateHandler(TimeSpan timeout)
17+
/// <remarks>This method is based on https://medium.com/@sawyer.watts/a-beginners-guide-to-net-s-hostbuilder-part-2-cancellation-857ae3e6ff02</remarks>
18+
public ConsoleCancelEventHandler CreateCancellationHandler(TimeSpan timeout)
2919
{
3020
return (_, cancelEvent) =>
3121
{
32-
if (_gracefulCancel)
22+
if (_isGracefulCancelled)
3323
{
3424
logger.LogInformation(
35-
"Received interrupt signal, attempting to shut down gracefully but will force-close in {Seconds} seconds. Send again to immediately force-close.",timeout.TotalSeconds);
25+
"Received interrupt signal, attempting to shut down gracefully but will force-close in {Seconds} seconds. Send again to immediately force-close.",
26+
timeout.TotalSeconds);
3627

37-
_cancellationTokenSource.Cancel();
28+
Cancel();
3829
cancelEvent.Cancel = true;
39-
_gracefulCancel = false;
30+
_isGracefulCancelled = false;
4031

4132
ForceExitAfterTimeout((int)timeout.TotalMilliseconds);
4233
}

0 commit comments

Comments
 (0)
Failed to load comments.