diff --git a/src/Extensions/NetDaemon.Extensions.Scheduling.Tests/Scheduling/DisposableSchedulerTest.cs b/src/Extensions/NetDaemon.Extensions.Scheduling.Tests/Scheduling/DisposableSchedulerTest.cs index c65f6ae6f..35c4cea11 100644 --- a/src/Extensions/NetDaemon.Extensions.Scheduling.Tests/Scheduling/DisposableSchedulerTest.cs +++ b/src/Extensions/NetDaemon.Extensions.Scheduling.Tests/Scheduling/DisposableSchedulerTest.cs @@ -78,6 +78,15 @@ public void SchedulePeriodicStopsAfterDisposeOfSubscriber() inner.AdvanceBy(TimeSpan.FromMinutes(1).Ticks); called.Should().Be(3); } + + [Fact] + public void DisposeTwice_NoException() + { + var (_, disposableScheduler) = CreateScheduler(); + + disposableScheduler.Dispose(); + disposableScheduler.Dispose(); + } private (TestScheduler inner, DisposableScheduler disposableScheduler) CreateScheduler() { diff --git a/src/Extensions/NetDaemon.Extensions.Scheduling.Tests/Scheduling/DisposableTimerTest.cs b/src/Extensions/NetDaemon.Extensions.Scheduling.Tests/Scheduling/DisposableTimerTest.cs new file mode 100644 index 000000000..5a6b1f46a --- /dev/null +++ b/src/Extensions/NetDaemon.Extensions.Scheduling.Tests/Scheduling/DisposableTimerTest.cs @@ -0,0 +1,17 @@ +using System.Threading; +using NetDaemon.Extensions.Scheduler; +using Xunit; + +namespace NetDaemon.Extensions.Scheduling.Tests; + +public class DisposableTimerTest +{ + [Fact] + public void DisposeTwice_NoException() + { + var timer = new DisposableTimer(CancellationToken.None); + + timer.Dispose(); + timer.Dispose(); + } +} \ No newline at end of file diff --git a/src/Extensions/NetDaemon.Extensions.Scheduling/DisposableScheduler.cs b/src/Extensions/NetDaemon.Extensions.Scheduling/DisposableScheduler.cs index a6fecaf5f..14ea29f24 100644 --- a/src/Extensions/NetDaemon.Extensions.Scheduling/DisposableScheduler.cs +++ b/src/Extensions/NetDaemon.Extensions.Scheduling/DisposableScheduler.cs @@ -76,9 +76,11 @@ public IDisposable Schedule(TState state, DateTimeOffset dueTime, Func public void Dispose() { - _isDisposed = true; - - _cancellationTokenSource.Cancel(); - _cancellationTokenSource.Dispose(); + if (!_isDisposed) + { + _cancellationTokenSource.Cancel(); + _cancellationTokenSource.Dispose(); + _isDisposed = true; + } } } \ No newline at end of file diff --git a/src/Extensions/NetDaemon.Extensions.Scheduling/DisposableTimer.cs b/src/Extensions/NetDaemon.Extensions.Scheduling/DisposableTimer.cs index 45ff0507f..e455eea7e 100644 --- a/src/Extensions/NetDaemon.Extensions.Scheduling/DisposableTimer.cs +++ b/src/Extensions/NetDaemon.Extensions.Scheduling/DisposableTimer.cs @@ -10,6 +10,8 @@ public sealed class DisposableTimer : IDisposable { private readonly CancellationTokenSource _combinedToken; private readonly CancellationTokenSource _internalToken; + private bool _disposed; + /// /// Constructor /// @@ -29,8 +31,11 @@ public DisposableTimer(CancellationToken token) /// public void Dispose() { - _internalToken.Cancel(); - _combinedToken.Dispose(); - _internalToken.Dispose(); + if (!_disposed){ + _internalToken.Cancel(); + _combinedToken.Dispose(); + _internalToken.Dispose(); + _disposed = true; + } } } \ No newline at end of file