diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs index 430fdaf1ae..3762ced7ea 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs @@ -339,7 +339,14 @@ private async Task GetAndUpdateAccountPropertiesAsync(Uri endpoint) if (databaseAccount != null) { this.AccountProperties = databaseAccount; - this.CancellationTokenSource.Cancel(); + try + { + this.CancellationTokenSource.Cancel(); + } + catch (ObjectDisposedException) + { + // Ignore the exception if the cancellation token source is already disposed + } } } catch (Exception e) @@ -348,7 +355,14 @@ private async Task GetAndUpdateAccountPropertiesAsync(Uri endpoint) if (GetAccountPropertiesHelper.IsNonRetriableException(e)) { DefaultTrace.TraceInformation("GlobalEndpointManager: Exception is not retriable"); - this.CancellationTokenSource.Cancel(); + try + { + this.CancellationTokenSource.Cancel(); + } + catch (ObjectDisposedException) + { + // Ignore the exception if the cancellation token source is already disposed + } this.NonRetriableException = e; } else @@ -405,15 +419,36 @@ private static IEnumerable GetServiceEndpoints( } } } - public void Dispose() { - if (Interlocked.Increment(ref this.disposeCounter) == 1) + // Dispose of unmanaged resources. + this.Dispose(true); + // Suppress finalization. + GC.SuppressFinalize(this); + } + protected virtual void Dispose(bool disposing) + { + if (Interlocked.Increment(ref this.disposeCounter) != 1) { - this.CancellationTokenSource?.Cancel(); - this.CancellationTokenSource?.Dispose(); + return; + } + + if (disposing) + { + try + { + this.CancellationTokenSource?.Cancel(); + this.CancellationTokenSource?.Dispose(); + } + catch (ObjectDisposedException) + { + // Ignore exceptions during dispose + } + } + } + } public virtual Uri ResolveServiceEndpoint(DocumentServiceRequest request) @@ -493,12 +528,20 @@ public void Dispose() { this.connectionPolicy.PreferenceChanged -= this.OnPreferenceChanged; if (!this.cancellationTokenSource.IsCancellationRequested) - { - // This can cause task canceled exceptions if the user disposes of the object while awaiting an async call. - this.cancellationTokenSource.Cancel(); - // The background timer task can hit a ObjectDisposedException but it's an async background task - // that is never awaited on so it will not be thrown back to the caller. - this.cancellationTokenSource.Dispose(); + { + try + { + // This can cause task canceled exceptions if the user disposes of the object while awaiting an async call. + this.cancellationTokenSource.Cancel(); + // The background timer task can hit a ObjectDisposedException but it's an async background task + // that is never awaited on so it will not be thrown back to the caller. + this.cancellationTokenSource.Dispose(); + } + catch (ObjectDisposedException) + { + // Ignore the exception if the cancellation token source is already disposed + + } } }