/// <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;
                }
            }
        }
Пример #2
0
        /// <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;
                }
            }
        }