1- namespace ServiceControl . Infrastructure . BackgroundTasks
1+ namespace ServiceControl . Infrastructure . BackgroundTasks ;
2+
3+ using System ;
4+ using System . Threading ;
5+ using System . Threading . Tasks ;
6+
7+ public enum TimerJobExecutionResult
28{
3- using System ;
4- using System . Threading ;
5- using System . Threading . Tasks ;
9+ ScheduleNextExecution ,
10+ ExecuteImmediately ,
11+ DoNotContinueExecuting
12+ }
613
7- public enum TimerJobExecutionResult
14+ public class TimerJob
15+ {
16+ public TimerJob ( Func < CancellationToken , Task < TimerJobExecutionResult > > callback , TimeSpan due , TimeSpan interval , Action < Exception > errorCallback )
817 {
9- ScheduleNextExecution ,
10- ExecuteImmediately ,
11- DoNotContinueExecuting
12- }
18+ tokenSource = new CancellationTokenSource ( ) ;
19+ var token = tokenSource . Token ;
1320
14- public class TimerJob
15- {
16- public TimerJob ( Func < CancellationToken , Task < TimerJobExecutionResult > > callback , TimeSpan due , TimeSpan interval , Action < Exception > errorCallback )
21+ task = Task . Run ( async ( ) =>
1722 {
18- tokenSource = new CancellationTokenSource ( ) ;
19- var token = tokenSource . Token ;
20-
21- task = Task . Run ( async ( ) =>
23+ try
2224 {
23- try
24- {
25- await Task . Delay ( due , token ) . ConfigureAwait ( false ) ;
25+ await Task . Delay ( due , token ) . ConfigureAwait ( false ) ;
2626
27- while ( ! token . IsCancellationRequested )
27+ while ( ! token . IsCancellationRequested )
28+ {
29+ try
2830 {
29- try
30- {
31- var result = await callback ( token ) . ConfigureAwait ( false ) ;
32- if ( result == TimerJobExecutionResult . DoNotContinueExecuting )
33- {
34- tokenSource . Cancel ( ) ;
35- }
36- else if ( result == TimerJobExecutionResult . ScheduleNextExecution )
37- {
38- await Task . Delay ( interval , token ) . ConfigureAwait ( false ) ;
39- }
40-
41- //Otherwise execute immediately
42- }
43- catch ( OperationCanceledException ) when ( token . IsCancellationRequested )
31+ var result = await callback ( token ) . ConfigureAwait ( false ) ;
32+ if ( result == TimerJobExecutionResult . DoNotContinueExecuting )
4433 {
45- break ;
34+ tokenSource . Cancel ( ) ;
4635 }
47- catch ( Exception ex )
36+ else if ( result == TimerJobExecutionResult . ScheduleNextExecution )
4837 {
49- errorCallback ( ex ) ;
38+ await Task . Delay ( interval , token ) . ConfigureAwait ( false ) ;
5039 }
40+
41+ //Otherwise execute immediately
42+ }
43+ catch ( OperationCanceledException ) when ( token . IsCancellationRequested )
44+ {
45+ break ;
46+ }
47+ catch ( Exception ex )
48+ {
49+ errorCallback ( ex ) ;
5150 }
5251 }
53- catch ( OperationCanceledException ) when ( token . IsCancellationRequested )
54- {
55- // no-op
56- }
57- } , CancellationToken . None ) ;
52+ }
53+ catch ( OperationCanceledException ) when ( token . IsCancellationRequested )
54+ {
55+ // no-op
56+ }
57+ } , CancellationToken . None ) ;
58+ }
59+
60+ public async Task Stop ( )
61+ {
62+ if ( tokenSource == null )
63+ {
64+ return ;
5865 }
5966
60- public async Task Stop ( )
67+ await tokenSource . CancelAsync ( ) . ConfigureAwait ( false ) ;
68+ tokenSource . Dispose ( ) ;
69+
70+ if ( task != null )
6171 {
62- if ( tokenSource == null )
72+ try
6373 {
64- return ;
74+ await task . ConfigureAwait ( false ) ;
6575 }
66-
67- await tokenSource . CancelAsync ( ) . ConfigureAwait ( false ) ;
68- tokenSource . Dispose ( ) ;
69-
70- if ( task != null )
76+ catch ( OperationCanceledException ) when ( tokenSource . IsCancellationRequested )
7177 {
72- try
73- {
74- await task . ConfigureAwait ( false ) ;
75- }
76- catch ( OperationCanceledException ) when ( tokenSource . IsCancellationRequested )
77- {
78- //NOOP
79- }
78+ //NOOP
8079 }
8180 }
82-
83- Task task ;
84- CancellationTokenSource tokenSource ;
8581 }
8682
87- public interface IAsyncTimer
88- {
89- TimerJob Schedule ( Func < CancellationToken , Task < TimerJobExecutionResult > > callback , TimeSpan due , TimeSpan interval , Action < Exception > errorCallback ) ;
90- }
83+ readonly Task task ;
84+ readonly CancellationTokenSource tokenSource ;
85+ }
9186
92- public class AsyncTimer : IAsyncTimer
93- {
94- public TimerJob Schedule ( Func < CancellationToken , Task < TimerJobExecutionResult > > callback , TimeSpan due , TimeSpan interval , Action < Exception > errorCallback ) => new TimerJob ( callback , due , interval , errorCallback ) ;
95- }
87+ public interface IAsyncTimer
88+ {
89+ TimerJob Schedule ( Func < CancellationToken , Task < TimerJobExecutionResult > > callback , TimeSpan due , TimeSpan interval , Action < Exception > errorCallback ) ;
90+ }
91+
92+ public class AsyncTimer : IAsyncTimer
93+ {
94+ public TimerJob Schedule ( Func < CancellationToken , Task < TimerJobExecutionResult > > callback , TimeSpan due , TimeSpan interval , Action < Exception > errorCallback ) => new ( callback , due , interval , errorCallback ) ;
9695}
0 commit comments