From 0aa4c6fc66334c8cab94b39ca7b46ce1d3727131 Mon Sep 17 00:00:00 2001 From: sakno Date: Tue, 12 Oct 2021 19:00:42 +0300 Subject: [PATCH 1/2] Suspend exception when trying to change the timer --- .../src/System/Threading/CancellationTokenSource.cs | 2 +- .../System.Private.CoreLib/src/System/Threading/Timer.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs index 54a7dc691cc0c..9ab26d8697cb1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -398,7 +398,7 @@ public bool TryReset() // If we successfully reset it and it never fired, then we can be sure it won't trigger cancellation. bool reset = _timer is not TimerQueueTimer timer || - (timer.Change(Timeout.UnsignedInfinite, Timeout.UnsignedInfinite) && !timer._everQueued); + (timer.Change(Timeout.UnsignedInfinite, Timeout.UnsignedInfinite, throwIfDisposed: false) && !timer._everQueued); if (reset) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs index 6b7e928cd5ba3..108034d778d42 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Timer.cs @@ -515,14 +515,14 @@ internal string DisplayString } } - internal bool Change(uint dueTime, uint period) + internal bool Change(uint dueTime, uint period, bool throwIfDisposed = true) { bool success; lock (_associatedTimerQueue) { if (_canceled) - throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic); + return throwIfDisposed ? throw new ObjectDisposedException(null, SR.ObjectDisposed_Generic) : false; _period = period; From 90d4c8c5b78febdfb6bbfd9b3fe833a719badea1 Mon Sep 17 00:00:00 2001 From: sakno Date: Tue, 12 Oct 2021 19:57:54 +0300 Subject: [PATCH 2/2] Replace try-catch with no-throw version of Change method --- .../System/Threading/CancellationTokenSource.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs index 9ab26d8697cb1..42b9dd61f5328 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -350,19 +350,7 @@ private void CancelAfter(uint millisecondsDelay) } } - // It is possible that _timer has already been disposed, so we must do - // the following in a try/catch block. - try - { - timer.Change(millisecondsDelay, Timeout.UnsignedInfinite); - } - catch (ObjectDisposedException) - { - // Just eat the exception. There is no other way to tell that - // the timer has been disposed, and even if there were, there - // would not be a good way to deal with the observe/dispose - // race condition. - } + timer.Change(millisecondsDelay, Timeout.UnsignedInfinite, throwIfDisposed: false); } ///