protected async Task WaitForIdleAsync(IExpeditableDelaySource expeditableDelaySource) { while (true) { if (CancellationToken.IsCancellationRequested) { return; } var diffInMS = Environment.TickCount - _lastAccessTimeInMS; if (diffInMS >= BackOffTimeSpanInMS) { return; } // TODO: will safestart/unwarp capture cancellation exception? var timeLeft = BackOffTimeSpanInMS - diffInMS; if (!await expeditableDelaySource.Delay(TimeSpan.FromMilliseconds(Math.Max(MinimumDelayInMS, timeLeft)), CancellationToken).ConfigureAwait(false)) { // The delay terminated early to accommodate a blocking operation. Make sure to delay long // enough that low priority (on idle) operations get a chance to be triggered. // // 📝 At the time this was discovered, it was not clear exactly why the delay was needed in order // to avoid live-lock scenarios. await Task.Delay(TimeSpan.FromMilliseconds(10), CancellationToken).ConfigureAwait(false); return; } } }
protected async Task WaitForIdleAsync(IExpeditableDelaySource expeditableDelaySource) { while (true) { if (CancellationToken.IsCancellationRequested) { return; } var diff = _timeSinceLastAccess.Elapsed; if (diff >= BackOffTimeSpan) { return; } // TODO: will safestart/unwarp capture cancellation exception? var timeLeft = BackOffTimeSpan - diff; if (!await expeditableDelaySource.Delay(TimeSpan.FromMilliseconds(Math.Max(s_minimumDelay.TotalMilliseconds, timeLeft.TotalMilliseconds)), CancellationToken).ConfigureAwait(false)) { // The delay terminated early to accommodate a blocking operation. Make sure to yield so low // priority (on idle) operations get a chance to be triggered. // // 📝 At the time this was discovered, it was not clear exactly why the yield (previously delay) // was needed in order to avoid live-lock scenarios. await Task.Yield().ConfigureAwait(false); return; } } }
private async Task StartTimerAsync(bool continueOnCapturedContext) { do { // Keep delaying until at least delayInMilliseconds has elapsed since lastSetTime if (!await _expeditableDelaySource.Delay(TimeSpan.FromMilliseconds(_delayInMilliseconds), CancellationToken.None).ConfigureAwait(continueOnCapturedContext)) { // The operation is being expedited. break; } }while (Environment.TickCount - _lastSetTime < _delayInMilliseconds); _taskCompletionSource.SetResult(null); }