From: Stephen Toub Date: Thu, 28 Jun 2018 14:26:21 +0000 (-0400) Subject: Avoid capturing ExecutionContext into CancellationTokenSource's Timer (dotnet/coreclr... X-Git-Tag: submit/tizen/20210909.063632~11030^2~4492 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=294d8b4244e1ccbb738f105437969834e880d86a;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Avoid capturing ExecutionContext into CancellationTokenSource's Timer (dotnet/coreclr#18670) * Avoid capturing ExecutionContext into CancellationTokenSource's Timer It's not needed, and it can keep unrelated state alive unnecessarily * Address PR feedback Commit migrated from https://github.com/dotnet/coreclr/commit/7d72463b1107cc6f264fcbdc06e3c4df0d9ed668 --- diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs index 7f41d25..d38ffc9 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -205,7 +205,7 @@ namespace System.Threading private void InitializeWithTimer(int millisecondsDelay) { _state = NotCanceledState; - _timer = new Timer(s_timerCallback, this, millisecondsDelay, -1); + _timer = new Timer(s_timerCallback, this, millisecondsDelay, -1, flowExecutionContext: false); } /// Communicates a request for cancellation. @@ -345,7 +345,7 @@ namespace System.Threading // Initially set to "never go off" because we don't want to take a // chance on a timer "losing" the initialization and then // cancelling the token before it (the timer) can be disposed. - Timer newTimer = new Timer(s_timerCallback, this, -1, -1); + Timer newTimer = new Timer(s_timerCallback, this, -1, -1, flowExecutionContext: false); if (Interlocked.CompareExchange(ref _timer, newTimer, null) != null) { // We did not initialize the timer. Dispose the new timer. diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs index eb02270..a8926bb 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs @@ -5419,7 +5419,7 @@ namespace System.Threading.Tasks // ... and create our timer and make sure that it stays rooted. if (millisecondsDelay != Timeout.Infinite) // no need to create the timer if it's an infinite timeout { - promise.Timer = new TimerQueueTimer(state => ((DelayPromise)state).Complete(), promise, (uint)millisecondsDelay, Timeout.UnsignedInfinite); + promise.Timer = new TimerQueueTimer(state => ((DelayPromise)state).Complete(), promise, (uint)millisecondsDelay, Timeout.UnsignedInfinite, flowExecutionContext: false); } // Return the timer proxy task diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Timer.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Timer.cs index 4d5c1c7..d9aa01e 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Timer.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Threading/Timer.cs @@ -440,13 +440,16 @@ namespace System.Threading private volatile WaitHandle m_notifyWhenNoCallbacksRunning; - internal TimerQueueTimer(TimerCallback timerCallback, object state, uint dueTime, uint period) + internal TimerQueueTimer(TimerCallback timerCallback, object state, uint dueTime, uint period, bool flowExecutionContext) { m_timerCallback = timerCallback; m_state = state; m_dueTime = Timeout.UnsignedInfinite; m_period = Timeout.UnsignedInfinite; - m_executionContext = ExecutionContext.Capture(); + if (flowExecutionContext) + { + m_executionContext = ExecutionContext.Capture(); + } m_associatedTimerQueue = TimerQueue.Instances[RuntimeThread.GetCurrentProcessorId() % TimerQueue.Instances.Length]; // @@ -677,14 +680,23 @@ namespace System.Threading public Timer(TimerCallback callback, object state, int dueTime, - int period) + int period) : + this(callback, state, dueTime, period, flowExecutionContext: true) + { + } + + internal Timer(TimerCallback callback, + object state, + int dueTime, + int period, + bool flowExecutionContext) { if (dueTime < -1) throw new ArgumentOutOfRangeException(nameof(dueTime), SR.ArgumentOutOfRange_NeedNonNegOrNegative1); if (period < -1) throw new ArgumentOutOfRangeException(nameof(period), SR.ArgumentOutOfRange_NeedNonNegOrNegative1); - TimerSetup(callback, state, (uint)dueTime, (uint)period); + TimerSetup(callback, state, (uint)dueTime, (uint)period, flowExecutionContext); } public Timer(TimerCallback callback, @@ -745,12 +757,13 @@ namespace System.Threading private void TimerSetup(TimerCallback callback, object state, uint dueTime, - uint period) + uint period, + bool flowExecutionContext = true) { if (callback == null) throw new ArgumentNullException(nameof(TimerCallback)); - m_timer = new TimerHolder(new TimerQueueTimer(callback, state, dueTime, period)); + m_timer = new TimerHolder(new TimerQueueTimer(callback, state, dueTime, period, flowExecutionContext)); } public bool Change(int dueTime, int period)