Пример #1
0
        /// <summary>
        /// The callback method that scans the pool for any end-of-life channels and purges them
        /// from the pool. This routine does not hold any locks so has to be pretty resilient about
        /// accessing and disposing of the channels which may well be used or removed at the time the
        /// cleanup occurs.
        /// </summary>
        //private void PoolCleanup(object sender, ElapsedEventArgs e)
        private void PoolCleanup()
        {
            Debug.WriteLine("in PoolCleanup event....");

            while (_runCleanupTask)
            {
                Thread.Sleep(Config.CleanupInterval * 1000);

                int currentChannelCount = 0;
                lock (_repopulateThread)
                {
                    DebugMessage("Cleanup process is checking pool status");

                    if (_channelList.Count > 0)
                    {
                        int latestCount = _channelList.Count - 1;

                        for (int cnt = latestCount; cnt >= 0; cnt--)
                        {
                            try
                            {
                                ChannelContext <TChannel> ch = _channelList[cnt];
                                if (IsChannelExpired(ch))
                                {
                                    DebugMessage(
                                        string.Format(
                                            "channel found that needs to be removed. ChannelOpened:{0}, Current Time:{1}",
                                            ch.DateTimeOpened.ToShortTimeString(), DateTime.Now.ToShortTimeString()));

                                    // needs to be purged.
                                    try
                                    {
                                        _channelList.RemoveAt(cnt);
                                        currentChannelCount++;
                                        if (((ICommunicationObject)ch.Channel).State == CommunicationState.Opened || ((ICommunicationObject)ch.Channel).State == CommunicationState.Created)
                                        {
                                            ((ICommunicationObject)ch.Channel).Close();
                                        }
                                    }
                                    catch (CommunicationException ce)
                                    {
                                        // do nothing here as well, the channel was already in a faulted state.
                                        DebugMessage("Channel to be removed was already in a faulted state");
                                    }
                                    catch (Exception ex)
                                    {
                                        // To get here means the number of channels in the pool was exhaused in between accessing the
                                        // initial element, so we leave things as they are and let the asynch process refill the pool.
                                        DebugMessage("Unable to remove channel. [" + ex.Message + "]");
                                    }
                                }
                            }
                            catch
                            {
                                // and again, we dont care if we are out of range
                                continue;
                            }
                        }
                    }
                }

                // Fire the ChannelPoolCollected event.
                ChannelPoolCollectedEventArgs cpea = new ChannelPoolCollectedEventArgs(currentChannelCount);
                OnChannelPoolCollected(cpea);
            }
        }
Пример #2
0
        /// <summary>
        /// The simple routine to refill the channel pool with opened channels.
        /// </summary>
        private void RefillPool(bool withLock)
        {
            DebugMessage("In RefillPool action");

            bool inSync = false;
            ChannelContext <TChannel> chanContext = null;

            try
            {
                int limit = Config.PoolSize - _channelList.Count;

                // If the pool is empty, lets obtain a lock and do a full refill
                if (_channelList.Count == 0)
                {
                    if (withLock)
                    {
                        if (!Monitor.TryEnter(_repopulateLock, Constants.LOCK_ATTEMPT_PERIOD))
                        {
                            throw new Exception(Constants.EXCEPTION_CANNOT_OBTAIN_LOCK_REFILL);
                        }
                        inSync = true;
                    }
                    limit = Config.PoolSize - _channelList.Count;
                }

                DebugMessage(string.Format("Number of Channels to RefillPool with: {0}", limit));

                for (int loop = 0; loop < limit; loop++)
                {
                    if (_channelList.Count <= Config.PoolSize)  // This is just a safeguard.
                    {
                        //TChannel chann = _channelFactory.CreateChannel();
                        TChannel chann = ChannelFactory.CreateChannel();
                        if (chann == null)
                        {
                            throw new Exception(Constants.EXCEPTION_CANNOT_CREATE_CHANNEL);
                        }

                        chanContext = new ChannelContext <TChannel>(chann);
                        try
                        {
                            ((ICommunicationObject)chann).Faulted += new EventHandler(ChannelPool_Faulted);
                            ((IChannel)chann).Open();
                            _channelList.Add(chanContext);
                        }
                        catch (CommunicationException ce)
                        {
                            // Typically, the initiation of the secure conversation has failed at this point as the server cannot process any more pending
                            // Secure conversations requirests.
                            string msg =
                                string.Format("Error opening a channel to add to the pool. [{0}\n{1}]", ce.Message,
                                              ce.InnerException != null ? ce.InnerException.Message : "");
                            DebugMessage(msg);
                            throw;
                            //break;
                        }
                    }


                    // If we didn't get a lock in the first place when adding in some proxies, and suddenly load increased and exhausted our pool
                    // then we check here
                    if (_channelList.Count == 0)
                    {
                        DebugMessage("Attempting secondary lock in refill...");
                        if (withLock)
                        {
                            if (!Monitor.TryEnter(_repopulateLock, Constants.LOCK_ATTEMPT_PERIOD))
                            {
                                throw new Exception("Canot get lock for refill!");
                            }
                            inSync = true;
                        }
                    }
                }
            }
            finally
            {
                if (inSync && withLock)
                {
                    Monitor.Exit(_repopulateLock);
                }
            }
        }