Skip to content

Commit 329d469

Browse files
committed
feat: Enable auto advance feature for timers
1 parent e0f8323 commit 329d469

12 files changed

+335
-17
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121

2222
- Enable auto advance feature for `GetTimestamp()` and `GetElapsedTime(long)`. To automatically advance time when `GetTimestamp()` or `GetElapsedTime(long)` is called, set `AutoAdvanceBehavior.TimestampAdvanceAmount` to a time span larger than zero.
2323

24+
- `ManualTimer` now exposes its current configuration. `DueTime`, `Period`, `IsActive`, `CallbackTime`, and `CallbackInvokeCount` are now publicly visible.
25+
26+
- Enable auto advance feature for timers. This enables automatically calling timers callback a specified number of times, by setting the `AutoAdvanceBehavior.TimerAutoTriggerCount` property to a number larger than zero.
27+
2428
## [1.0.0-rc.1]
2529

2630
- Updated Microsoft.Bcl.TimeProvider package dependency to rc.1 version.

docs/TimeProviderExtensions.AutoAdvanceBehavior.md

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,39 @@ Inheritance [System.Object](https://docs.microsoft.com/en-us/dotnet/api/System.O
1515
Implements [System.IEquatable<](https://docs.microsoft.com/en-us/dotnet/api/System.IEquatable-1 'System.IEquatable`1')[AutoAdvanceBehavior](TimeProviderExtensions.AutoAdvanceBehavior.md 'TimeProviderExtensions.AutoAdvanceBehavior')[>](https://docs.microsoft.com/en-us/dotnet/api/System.IEquatable-1 'System.IEquatable`1')
1616
### Properties
1717

18-
<a name='TimeProviderExtensions.AutoAdvanceBehavior.ClockAdvanceAmount'></a>
18+
<a name='TimeProviderExtensions.AutoAdvanceBehavior.TimerAutoTriggerCount'></a>
1919

20-
## AutoAdvanceBehavior.ClockAdvanceAmount Property
20+
## AutoAdvanceBehavior.TimerAutoTriggerCount Property
2121

22-
Gets or sets the amount of time by which time advances whenever the clock is read via [System.TimeProvider.GetUtcNow](https://docs.microsoft.com/en-us/dotnet/api/System.TimeProvider.GetUtcNow 'System.TimeProvider.GetUtcNow')
23-
or [System.TimeProvider.GetLocalNow](https://docs.microsoft.com/en-us/dotnet/api/System.TimeProvider.GetLocalNow 'System.TimeProvider.GetLocalNow').
22+
23+
Gets or sets the amount of times timer callbacks will automatically be triggered.
24+
25+
Setting this to a number greater than `0` causes any active timers to have their callback invoked until they have been invoked the number of times
26+
specified by [TimerAutoTriggerCount](TimeProviderExtensions.AutoAdvanceBehavior.md#TimeProviderExtensions.AutoAdvanceBehavior.TimerAutoTriggerCount 'TimeProviderExtensions.AutoAdvanceBehavior.TimerAutoTriggerCount'). Before timer callbacks are invoked, time is advanced to match
27+
the time the callback was scheduled to be invoked, just as it is if [Advance(TimeSpan)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.Advance(System.TimeSpan) 'TimeProviderExtensions.ManualTimeProvider.Advance(System.TimeSpan)')
28+
or [SetUtcNow(DateTimeOffset)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.SetUtcNow(System.DateTimeOffset) 'TimeProviderExtensions.ManualTimeProvider.SetUtcNow(System.DateTimeOffset)') was manually called.
29+
30+
Setting this to `1` can be used to ensure all timers, e.g. those used by [Task.Delay(TimeSpan, TimeProvider)](https://docs.microsoft.com/en-us/dotnet/api/Task.Delay#Task_Delay_TimeSpan, TimeProvider_ 'Task.Delay(TimeSpan, TimeProvider)'),
31+
[Task.WaitAsync(TimeSpan, TimeProvider)](https://docs.microsoft.com/en-us/dotnet/api/Task.WaitAsync#Task_WaitAsync_TimeSpan, TimeProvider_ 'Task.WaitAsync(TimeSpan, TimeProvider)'), [System.Threading.CancellationTokenSource.CancelAfter(System.TimeSpan)](https://docs.microsoft.com/en-us/dotnet/api/System.Threading.CancellationTokenSource.CancelAfter#System_Threading_CancellationTokenSource_CancelAfter_System_TimeSpan_ 'System.Threading.CancellationTokenSource.CancelAfter(System.TimeSpan)') and others
32+
are completed immediately.
33+
34+
Setting this to a number larger than `1`, e.g. `10`, can be used to automatically cause a [PeriodicTimer(TimeSpan, TimeProvider)](https://docs.microsoft.com/en-us/dotnet/api/PeriodicTimer#PeriodicTimer_TimeSpan, TimeProvider_ 'PeriodicTimer(TimeSpan, TimeProvider)')
35+
to automatically have its [System.Threading.PeriodicTimer.WaitForNextTickAsync(System.Threading.CancellationToken)](https://docs.microsoft.com/en-us/dotnet/api/System.Threading.PeriodicTimer.WaitForNextTickAsync#System_Threading_PeriodicTimer_WaitForNextTickAsync_System_Threading_CancellationToken_ 'System.Threading.PeriodicTimer.WaitForNextTickAsync(System.Threading.CancellationToken)') async enumerable return `10` times.
2436
2537
```csharp
26-
public System.TimeSpan ClockAdvanceAmount { get; set; }
38+
public int TimerAutoTriggerCount { get; set; }
2739
```
2840

2941
#### Property Value
30-
[System.TimeSpan](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan 'System.TimeSpan')
42+
[System.Int32](https://docs.microsoft.com/en-us/dotnet/api/System.Int32 'System.Int32')
3143
3244
#### Exceptions
3345

3446
[System.ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/System.ArgumentOutOfRangeException 'System.ArgumentOutOfRangeException')
35-
Thrown when set to a value less than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').
47+
Thrown when set to a value less than zero `0`.
3648

3749
### Remarks
38-
Set to [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero') to disable auto advance. The default value is [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').
50+
Set to `0` to disable auto timer callback invocation. The default value is zero `0`.
3951

4052
<a name='TimeProviderExtensions.AutoAdvanceBehavior.TimestampAdvanceAmount'></a>
4153

@@ -56,5 +68,27 @@ public System.TimeSpan TimestampAdvanceAmount { get; set; }
5668
[System.ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/System.ArgumentOutOfRangeException 'System.ArgumentOutOfRangeException')
5769
Thrown when set to a value less than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').
5870
71+
### Remarks
72+
Set to [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero') to disable auto advance. The default value is [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').
73+
74+
<a name='TimeProviderExtensions.AutoAdvanceBehavior.UtcNowAdvanceAmount'></a>
75+
76+
## AutoAdvanceBehavior.UtcNowAdvanceAmount Property
77+
78+
Gets or sets the amount of time by which time advances whenever the clock is read via [System.TimeProvider.GetUtcNow](https://docs.microsoft.com/en-us/dotnet/api/System.TimeProvider.GetUtcNow 'System.TimeProvider.GetUtcNow')
79+
or [System.TimeProvider.GetLocalNow](https://docs.microsoft.com/en-us/dotnet/api/System.TimeProvider.GetLocalNow 'System.TimeProvider.GetLocalNow').
80+
81+
```csharp
82+
public System.TimeSpan UtcNowAdvanceAmount { get; set; }
83+
```
84+
85+
#### Property Value
86+
[System.TimeSpan](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan 'System.TimeSpan')
87+
88+
#### Exceptions
89+
90+
[System.ArgumentOutOfRangeException](https://docs.microsoft.com/en-us/dotnet/api/System.ArgumentOutOfRangeException 'System.ArgumentOutOfRangeException')
91+
Thrown when set to a value less than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').
92+
5993
### Remarks
6094
Set to [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero') to disable auto advance. The default value is [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero').

docs/TimeProviderExtensions.ManualTimeProvider.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ If the desired result is to jump time by [delta](TimeProviderExtensions.ManualTi
204204
the expected number of times, i.e. such that the result of `manualTimeProvider.GetElapsedTime(start)` in the callback is
205205
<em>3 seconds</em>, <em>3 seconds</em>, and <em>3 seconds</em>, use [Jump(DateTimeOffset)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.Jump(System.DateTimeOffset) 'TimeProviderExtensions.ManualTimeProvider.Jump(System.DateTimeOffset)') or [Jump(TimeSpan)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.Jump(System.TimeSpan) 'TimeProviderExtensions.ManualTimeProvider.Jump(System.TimeSpan)') instead.
206206

207-
Learn more about this behavior at <seealso href="https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider"/>.
207+
Learn more about this behavior at [https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider](https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider 'https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider').
208208
209209
<a name='TimeProviderExtensions.ManualTimeProvider.CreateManualTimer(System.Threading.TimerCallback,object,TimeProviderExtensions.ManualTimeProvider)'></a>
210210

@@ -250,7 +250,7 @@ the provided timer [callback](TimeProviderExtensions.ManualTimeProvider.md#TimeP
250250
Creates a new [System.Threading.ITimer](https://docs.microsoft.com/en-us/dotnet/api/System.Threading.ITimer 'System.Threading.ITimer') instance, using [System.TimeSpan](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan 'System.TimeSpan') values to measure time intervals.
251251
252252
```csharp
253-
public sealed override System.Threading.ITimer CreateTimer(System.Threading.TimerCallback callback, object? state, System.TimeSpan dueTime, System.TimeSpan period);
253+
public TimeProviderExtensions.ManualTimer CreateTimer(System.Threading.TimerCallback callback, object? state, System.TimeSpan dueTime, System.TimeSpan period);
254254
```
255255
#### Parameters
256256

@@ -280,7 +280,7 @@ The amount of time to delay before [callback](TimeProviderExtensions.ManualTimeP
280280
The time interval between invocations of [callback](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.CreateTimer(System.Threading.TimerCallback,object,System.TimeSpan,System.TimeSpan).callback 'TimeProviderExtensions.ManualTimeProvider.CreateTimer(System.Threading.TimerCallback, object, System.TimeSpan, System.TimeSpan).callback'). Specify [System.Threading.Timeout.InfiniteTimeSpan](https://docs.microsoft.com/en-us/dotnet/api/System.Threading.Timeout.InfiniteTimeSpan 'System.Threading.Timeout.InfiniteTimeSpan') to disable periodic signaling.
281281
282282
#### Returns
283-
[System.Threading.ITimer](https://docs.microsoft.com/en-us/dotnet/api/System.Threading.ITimer 'System.Threading.ITimer')
283+
[ManualTimer](TimeProviderExtensions.ManualTimer.md 'TimeProviderExtensions.ManualTimer')
284284
The newly created [System.Threading.ITimer](https://docs.microsoft.com/en-us/dotnet/api/System.Threading.ITimer 'System.Threading.ITimer') instance.
285285
286286
#### Exceptions
@@ -348,8 +348,8 @@ public override System.DateTimeOffset GetUtcNow();
348348
[System.DateTimeOffset](https://docs.microsoft.com/en-us/dotnet/api/System.DateTimeOffset 'System.DateTimeOffset')
349349
350350
### Remarks
351-
If [ClockAdvanceAmount](TimeProviderExtensions.AutoAdvanceBehavior.md#TimeProviderExtensions.AutoAdvanceBehavior.ClockAdvanceAmount 'TimeProviderExtensions.AutoAdvanceBehavior.ClockAdvanceAmount') is greater than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero'), calling this
352-
method will move time forward by the amount specified by [ClockAdvanceAmount](TimeProviderExtensions.AutoAdvanceBehavior.md#TimeProviderExtensions.AutoAdvanceBehavior.ClockAdvanceAmount 'TimeProviderExtensions.AutoAdvanceBehavior.ClockAdvanceAmount').
351+
If [UtcNowAdvanceAmount](TimeProviderExtensions.AutoAdvanceBehavior.md#TimeProviderExtensions.AutoAdvanceBehavior.UtcNowAdvanceAmount 'TimeProviderExtensions.AutoAdvanceBehavior.UtcNowAdvanceAmount') is greater than [System.TimeSpan.Zero](https://docs.microsoft.com/en-us/dotnet/api/System.TimeSpan.Zero 'System.TimeSpan.Zero'), calling this
352+
method will move time forward by the amount specified by [UtcNowAdvanceAmount](TimeProviderExtensions.AutoAdvanceBehavior.md#TimeProviderExtensions.AutoAdvanceBehavior.UtcNowAdvanceAmount 'TimeProviderExtensions.AutoAdvanceBehavior.UtcNowAdvanceAmount').
353353
The [System.DateTimeOffset](https://docs.microsoft.com/en-us/dotnet/api/System.DateTimeOffset 'System.DateTimeOffset') returned from this method will reflect the time before
354354
the auto advance was applied, if any.
355355

@@ -407,7 +407,7 @@ If the desired result is that timer callbacks happens exactly at their scheduled
407407
of `manualTimeProvider.GetElapsedTime(start)` in the callback will be <em>1 second</em>, <em>2 seconds</em>, and <em>3 seconds</em>,
408408
use [Advance(TimeSpan)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.Advance(System.TimeSpan) 'TimeProviderExtensions.ManualTimeProvider.Advance(System.TimeSpan)') or [SetUtcNow(DateTimeOffset)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.SetUtcNow(System.DateTimeOffset) 'TimeProviderExtensions.ManualTimeProvider.SetUtcNow(System.DateTimeOffset)') instead.
409409

410-
Learn more about this behavior at <seealso href="https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider"/>.
410+
Learn more about this behavior at [https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider](https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider 'https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider').
411411
412412
<a name='TimeProviderExtensions.ManualTimeProvider.Jump(System.TimeSpan)'></a>
413413

@@ -462,7 +462,7 @@ If the desired result is that timer callbacks happens exactly at their scheduled
462462
of `manualTimeProvider.GetElapsedTime(start)` in the callback will be <em>1 second</em>, <em>2 seconds</em>, and <em>3 seconds</em>,
463463
use [Advance(TimeSpan)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.Advance(System.TimeSpan) 'TimeProviderExtensions.ManualTimeProvider.Advance(System.TimeSpan)') or [SetUtcNow(DateTimeOffset)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.SetUtcNow(System.DateTimeOffset) 'TimeProviderExtensions.ManualTimeProvider.SetUtcNow(System.DateTimeOffset)') instead.
464464

465-
Learn more about this behavior at <seealso href="https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider"/>.
465+
Learn more about this behavior at [https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider](https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider 'https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider').
466466
467467
<a name='TimeProviderExtensions.ManualTimeProvider.SetLocalTimeZone(System.TimeZoneInfo)'></a>
468468

@@ -536,7 +536,7 @@ If the desired result is to jump to the time specified in [value](TimeProviderEx
536536
the expected number of times, i.e. such that the result of `manualTimeProvider.GetElapsedTime(start)` in the callback is
537537
<em>3 seconds</em>, <em>3 seconds</em>, and <em>3 seconds</em>, use [Jump(DateTimeOffset)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.Jump(System.DateTimeOffset) 'TimeProviderExtensions.ManualTimeProvider.Jump(System.DateTimeOffset)') or [Jump(TimeSpan)](TimeProviderExtensions.ManualTimeProvider.md#TimeProviderExtensions.ManualTimeProvider.Jump(System.TimeSpan) 'TimeProviderExtensions.ManualTimeProvider.Jump(System.TimeSpan)') instead.
538538

539-
Learn more about this behavior at <seealso href="https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider"/>.
539+
Learn more about this behavior at [https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider](https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider 'https://github.com/egil/TimeProviderExtensions/#difference-between-manualtimeprovider-and-faketimeprovider').
540540
541541
<a name='TimeProviderExtensions.ManualTimeProvider.ToString()'></a>
542542

docs/TimeProviderExtensions.ManualTimer.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,19 @@ An object to be passed to the [callback](TimeProviderExtensions.ManualTimer.md#T
4848
The [ManualTimeProvider](TimeProviderExtensions.ManualTimeProvider.md 'TimeProviderExtensions.ManualTimeProvider') which is used to schedule invocations of the [callback](TimeProviderExtensions.ManualTimer.md#TimeProviderExtensions.ManualTimer.ManualTimer(System.Threading.TimerCallback,object,TimeProviderExtensions.ManualTimeProvider).callback 'TimeProviderExtensions.ManualTimer.ManualTimer(System.Threading.TimerCallback, object, TimeProviderExtensions.ManualTimeProvider).callback') with.
4949
### Properties
5050

51+
<a name='TimeProviderExtensions.ManualTimer.CallbackInvokeCount'></a>
52+
53+
## ManualTimer.CallbackInvokeCount Property
54+
55+
Gets the number of times a timer's callback has been invoked.
56+
57+
```csharp
58+
public int CallbackInvokeCount { get; }
59+
```
60+
61+
#### Property Value
62+
[System.Int32](https://docs.microsoft.com/en-us/dotnet/api/System.Int32 'System.Int32')
63+
5164
<a name='TimeProviderExtensions.ManualTimer.CallbackTime'></a>
5265

5366
## ManualTimer.CallbackTime Property

0 commit comments

Comments
 (0)