/// <summary>Initializes the pools.</summary> public HttpConnectionPoolManager(HttpConnectionSettings settings) { _settings = settings; _maxConnectionsPerServer = settings._maxConnectionsPerServer; _avoidStoringConnections = settings._pooledConnectionIdleTimeout == TimeSpan.Zero || settings._pooledConnectionLifetime == TimeSpan.Zero; _pools = new ConcurrentDictionary <HttpConnectionKey, HttpConnectionPool>(); // Start out with the timer not running, since we have no pools. // When it does run, run it with a frequency based on the idle timeout. if (!_avoidStoringConnections) { if (settings._pooledConnectionIdleTimeout == Timeout.InfiniteTimeSpan) { const int DefaultScavengeSeconds = 30; _cleanPoolTimeout = TimeSpan.FromSeconds(DefaultScavengeSeconds); } else { const int ScavengesPerIdle = 4; const int MinScavengeSeconds = 1; TimeSpan timerPeriod = settings._pooledConnectionIdleTimeout / ScavengesPerIdle; _cleanPoolTimeout = timerPeriod.TotalSeconds >= MinScavengeSeconds ? timerPeriod : TimeSpan.FromSeconds(MinScavengeSeconds); } bool restoreFlow = false; try { // Don't capture the current ExecutionContext and its AsyncLocals onto the timer causing them to live forever if (!ExecutionContext.IsFlowSuppressed()) { ExecutionContext.SuppressFlow(); restoreFlow = true; } _cleaningTimer = new Timer(s => ((HttpConnectionPoolManager)s).RemoveStalePools(), this, Timeout.Infinite, Timeout.Infinite); } finally { // Restore the current ExecutionContext if (restoreFlow) { ExecutionContext.RestoreFlow(); } } } // Figure out proxy stuff. if (settings._useProxy) { _proxy = settings._proxy ?? SystemProxyInfo.ConstructSystemProxy(); if (_proxy != null) { _proxyCredentials = _proxy.Credentials ?? settings._defaultProxyCredentials; } } }
/// <summary>Initializes the pools.</summary> public HttpConnectionPoolManager(HttpConnectionSettings settings) { _settings = settings; _maxConnectionsPerServer = settings._maxConnectionsPerServer; _pools = new ConcurrentDictionary <HttpConnectionKey, HttpConnectionPool>(); // As an optimization, we can sometimes avoid the overheads associated with // storing connections. This is possible when we would immediately terminate // connections anyway due to either the idle timeout or the lifetime being // set to zero, as in that case the timeout effectively immediately expires. // However, we can only do such optimizations if we're not also tracking // connections per server, as we use data in the associated data structures // to do that tracking. bool avoidStoringConnections = settings._maxConnectionsPerServer == int.MaxValue && (settings._pooledConnectionIdleTimeout == TimeSpan.Zero || settings._pooledConnectionLifetime == TimeSpan.Zero); // Start out with the timer not running, since we have no pools. // When it does run, run it with a frequency based on the idle timeout. if (!avoidStoringConnections) { if (settings._pooledConnectionIdleTimeout == Timeout.InfiniteTimeSpan) { const int DefaultScavengeSeconds = 30; _cleanPoolTimeout = TimeSpan.FromSeconds(DefaultScavengeSeconds); } else { const int ScavengesPerIdle = 4; const int MinScavengeSeconds = 1; TimeSpan timerPeriod = settings._pooledConnectionIdleTimeout / ScavengesPerIdle; _cleanPoolTimeout = timerPeriod.TotalSeconds >= MinScavengeSeconds ? timerPeriod : TimeSpan.FromSeconds(MinScavengeSeconds); } bool restoreFlow = false; try { // Don't capture the current ExecutionContext and its AsyncLocals onto the timer causing them to live forever if (!ExecutionContext.IsFlowSuppressed()) { ExecutionContext.SuppressFlow(); restoreFlow = true; } // Create the timer. Ensure the Timer has a weak reference to this manager; otherwise, it // can introduce a cycle that keeps the HttpConnectionPoolManager rooted by the Timer // implementation until the handler is Disposed (or indefinitely if it's not). _cleaningTimer = new Timer(s => { var wr = (WeakReference <HttpConnectionPoolManager>)s; if (wr.TryGetTarget(out HttpConnectionPoolManager thisRef)) { thisRef.RemoveStalePools(); } }, new WeakReference <HttpConnectionPoolManager>(this), Timeout.Infinite, Timeout.Infinite); } finally { // Restore the current ExecutionContext if (restoreFlow) { ExecutionContext.RestoreFlow(); } } } // Figure out proxy stuff. if (settings._useProxy) { _proxy = settings._proxy ?? SystemProxyInfo.ConstructSystemProxy(); if (_proxy != null) { _proxyCredentials = _proxy.Credentials ?? settings._defaultProxyCredentials; } } }
/// <summary>Initializes the pools.</summary> public HttpConnectionPoolManager(HttpConnectionSettings settings) { _settings = settings; _maxConnectionsPerServer = settings._maxConnectionsPerServer; _avoidStoringConnections = settings._pooledConnectionIdleTimeout == TimeSpan.Zero || settings._pooledConnectionLifetime == TimeSpan.Zero; _pools = new ConcurrentDictionary <HttpConnectionKey, HttpConnectionPool>(); // Start out with the timer not running, since we have no pools. // When it does run, run it with a frequency based on the idle timeout. if (!_avoidStoringConnections) { if (settings._pooledConnectionIdleTimeout == Timeout.InfiniteTimeSpan) { const int DefaultScavengeSeconds = 30; _cleanPoolTimeout = TimeSpan.FromSeconds(DefaultScavengeSeconds); } else { const int ScavengesPerIdle = 4; const int MinScavengeSeconds = 1; TimeSpan timerPeriod = settings._pooledConnectionIdleTimeout / ScavengesPerIdle; _cleanPoolTimeout = timerPeriod.TotalSeconds >= MinScavengeSeconds ? timerPeriod : TimeSpan.FromSeconds(MinScavengeSeconds); } bool restoreFlow = false; try { // Don't capture the current ExecutionContext and its AsyncLocals onto the timer causing them to live forever if (!ExecutionContext.IsFlowSuppressed()) { ExecutionContext.SuppressFlow(); restoreFlow = true; } // Create the timer. Ensure the Timer has a weak reference to this manager; otherwise, it // can introduce a cycle that keeps the HttpConnectionPoolManager rooted by the Timer // implementation until the handler is Disposed (or indefinitely if it's not). _cleaningTimer = new Timer(s => { var wr = (WeakReference <HttpConnectionPoolManager>)s; if (wr.TryGetTarget(out HttpConnectionPoolManager thisRef)) { thisRef.RemoveStalePools(); } }, new WeakReference <HttpConnectionPoolManager>(this), Timeout.Infinite, Timeout.Infinite); } finally { // Restore the current ExecutionContext if (restoreFlow) { ExecutionContext.RestoreFlow(); } } } // Figure out proxy stuff. if (settings._useProxy) { _proxy = settings._proxy ?? SystemProxyInfo.ConstructSystemProxy(); if (_proxy != null) { _proxyCredentials = _proxy.Credentials ?? settings._defaultProxyCredentials; } } }