-
Notifications
You must be signed in to change notification settings - Fork 5
Add Timer class polyfill for .NET Standard 1.0–1.1 via Task.Delay
#81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
5874690
2e6b4b3
69ef4db
2be4f52
585ca1f
fed084c
ac45d37
2cc00c7
4703f2b
7f70deb
6e859db
458a10a
5b71532
9a54c8b
03a32ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| #if NETSTANDARD && !NETSTANDARD1_2_OR_GREATER | ||
| #nullable enable | ||
| // ReSharper disable RedundantUsingDirective | ||
| // ReSharper disable CheckNamespace | ||
| // ReSharper disable InconsistentNaming | ||
| // ReSharper disable PartialTypeWithSinglePart | ||
|
|
||
| using System.Diagnostics.CodeAnalysis; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace System.Threading; | ||
|
|
||
| // https://learn.microsoft.com/dotnet/api/system.threading.timer | ||
| [ExcludeFromCodeCoverage] | ||
| internal sealed class Timer : IDisposable | ||
| { | ||
| private readonly TimerCallback _callback; | ||
| private readonly object? _state; | ||
| private CancellationTokenSource _cts = new CancellationTokenSource(); | ||
| private volatile bool _disposed; | ||
|
|
||
| public Timer(TimerCallback callback, object? state, TimeSpan dueTime, TimeSpan period) | ||
| { | ||
|
Tyrrrz marked this conversation as resolved.
Outdated
|
||
| _callback = callback; | ||
| _state = state; | ||
| Schedule(dueTime, period); | ||
| } | ||
|
Tyrrrz marked this conversation as resolved.
|
||
|
|
||
| public Timer(TimerCallback callback, object? state, int dueTime, int period) | ||
| : this( | ||
| callback, | ||
| state, | ||
| TimeSpan.FromMilliseconds(dueTime), | ||
| TimeSpan.FromMilliseconds(period) | ||
| ) { } | ||
|
|
||
| public Timer(TimerCallback callback, object? state, long dueTime, long period) | ||
| : this( | ||
| callback, | ||
| state, | ||
| TimeSpan.FromMilliseconds(dueTime), | ||
| TimeSpan.FromMilliseconds(period) | ||
| ) { } | ||
|
|
||
| public Timer(TimerCallback callback) | ||
| : this(callback, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan) { } | ||
|
|
||
| private void Schedule(TimeSpan dueTime, TimeSpan period) | ||
| { | ||
| if (_disposed) | ||
| throw new ObjectDisposedException(nameof(Timer)); | ||
|
|
||
| var cts = new CancellationTokenSource(); | ||
| var oldCts = Interlocked.Exchange(ref _cts, cts); | ||
| oldCts.Cancel(); | ||
| oldCts.Dispose(); | ||
|
|
||
| if (dueTime == Timeout.InfiniteTimeSpan) | ||
| return; | ||
|
|
||
| _ = Task.Run(async () => | ||
| { | ||
| try | ||
| { | ||
| if (dueTime > TimeSpan.Zero) | ||
| await Task.Delay(dueTime, cts.Token); | ||
|
|
||
| if (cts.IsCancellationRequested) | ||
| return; | ||
|
|
||
| _callback(_state); | ||
|
|
||
| if (period == Timeout.InfiniteTimeSpan || period <= TimeSpan.Zero) | ||
| return; | ||
|
||
|
|
||
| while (!cts.IsCancellationRequested) | ||
| { | ||
| await Task.Delay(period, cts.Token); | ||
|
|
||
| if (cts.IsCancellationRequested) | ||
| return; | ||
|
|
||
| _callback(_state); | ||
| } | ||
| } | ||
| catch (OperationCanceledException) { } | ||
| }); | ||
|
Tyrrrz marked this conversation as resolved.
|
||
| } | ||
|
|
||
| public bool Change(TimeSpan dueTime, TimeSpan period) | ||
| { | ||
| try | ||
| { | ||
| Schedule(dueTime, period); | ||
| return true; | ||
| } | ||
| catch | ||
| { | ||
| return false; | ||
| } | ||
|
Tyrrrz marked this conversation as resolved.
Tyrrrz marked this conversation as resolved.
|
||
| } | ||
|
|
||
| public bool Change(int dueTime, int period) => | ||
| Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period)); | ||
|
|
||
| public bool Change(long dueTime, long period) => | ||
| Change(TimeSpan.FromMilliseconds(dueTime), TimeSpan.FromMilliseconds(period)); | ||
|
|
||
| public void Dispose() | ||
| { | ||
| if (_disposed) | ||
| return; | ||
| _disposed = true; | ||
|
Tyrrrz marked this conversation as resolved.
|
||
| var cts = Interlocked.Exchange(ref _cts, new CancellationTokenSource()); | ||
| cts.Cancel(); | ||
| cts.Dispose(); | ||
|
||
| } | ||
|
Tyrrrz marked this conversation as resolved.
|
||
| } | ||
| #endif | ||
Uh oh!
There was an error while loading. Please reload this page.