public bool Purge(bool purgeAll)
            {
                bool foundDirt = false;

                if (!purgeAll)
                {
                    // copy the keys into a separate array, so that later on
                    // we can change the dictionary while iterating over the keys
                    ICollection ic   = _dict.Keys;
                    String[]    keys = new String[ic.Count];
                    ic.CopyTo(keys, 0);

                    for (int i = keys.Length - 1; i >= 0; --i)
                    {
                        if (keys[i] == AllListenersKey)
                        {
                            continue;       // ignore the special entry for now
                        }
                        // for each key, remove dead entries in its list
                        PropertyRecord pr = (PropertyRecord)_dict[keys[i]];
                        if (pr.Purge())
                        {
                            foundDirt = true;
                        }

                        // if there are no more entries, remove the key
                        if (pr.IsEmpty)
                        {
                            pr.StopListening(_type);
                            _dict.Remove(keys[i]);
                        }
                    }

                    if (foundDirt)
                    {
                        // if any entries were purged, invalidate the special entry
                        _dict.Remove(AllListenersKey);
                        _proposedAllListenersList = null;
                    }

                    if (IsEmpty)
                    {
                        StopListening();
                    }
                }
                else
                {
                    // stop listening.  List cleanup is handled by Purge()
                    foundDirt = true;
                    StopListening();

                    foreach (DictionaryEntry de in _dict)
                    {
                        PropertyRecord pr = (PropertyRecord)de.Value;
                        pr.StopListening(_type);
                    }
                }

                return(foundDirt);
            }
コード例 #2
0
            public bool Purge(bool purgeAll)
            {
                bool foundDirt = false;

                if (!purgeAll)
                {
                    if (!MS.Internal.BaseAppContextSwitches.EnableWeakEventMemoryImprovements)
                    {
                        // copy the keys into a separate array, so that later on
                        // we can change the dictionary while iterating over the keys
                        ICollection ic   = _dict.Keys;
                        String[]    keys = new String[ic.Count];
                        ic.CopyTo(keys, 0);

                        for (int i = keys.Length - 1; i >= 0; --i)
                        {
                            if (keys[i] == AllListenersKey)
                            {
                                continue;       // ignore the special entry for now
                            }
                            // for each key, remove dead entries in its list
                            PropertyRecord pr = (PropertyRecord)_dict[keys[i]];
                            if (pr.Purge())
                            {
                                foundDirt = true;
                            }

                            // if there are no more entries, remove the key
                            if (pr.IsEmpty)
                            {
                                pr.StopListening(_type);
                                _dict.Remove(keys[i]);
                            }
                        }

#if WeakEventTelemetry
                        _manager.LogAllocationRelay(ic.GetType(), 1, 12);                    // dict.Keys - Hashtable+KeyCollection
                        _manager.LogAllocationRelay(typeof(String[]), 1, 12 + ic.Count * 4); // keys
#endif
                    }
                    else
                    {
                        Debug.Assert(_toRemove.Count == 0, "to-remove list should be empty");

                        // enumerate the dictionary using IDE explicitly rather than
                        // foreach, to avoid allocating temporary DictionaryEntry objects
                        IDictionaryEnumerator ide = _dict.GetEnumerator() as IDictionaryEnumerator;
                        while (ide.MoveNext())
                        {
                            String key = (String)ide.Key;
                            if (key == AllListenersKey)
                            {
                                continue;       // ignore the special entry for now
                            }
                            // for each key, remove dead entries in its list
                            PropertyRecord pr = (PropertyRecord)ide.Value;
                            if (pr.Purge())
                            {
                                foundDirt = true;
                            }

                            // if there are no more entries, remove the key
                            if (pr.IsEmpty)
                            {
                                pr.StopListening(_type);
                                _toRemove.Add(key);
                            }
                        }

                        // do the actual removal (outside the dictionary iteration)
                        if (_toRemove.Count > 0)
                        {
                            foreach (String key in _toRemove)
                            {
                                _dict.Remove(key);
                            }
                            _toRemove.Clear();
                            _toRemove.TrimExcess();
                        }

#if WeakEventTelemetry
                        Type enumeratorType = ide.GetType();
                        if (enumeratorType.Name.IndexOf("NodeEnumerator") >= 0)
                        {
                            _manager.LogAllocationRelay(enumeratorType, 1, 24); // ListDictionary+NodeEnumerator
                        }
                        else
                        {
                            _manager.LogAllocationRelay(enumeratorType, 1, 36); // Hashtable+HashtableEnumerator
                        }
#endif
                    }

                    if (foundDirt)
                    {
                        // if any entries were purged, invalidate the special entry
                        _dict.Remove(AllListenersKey);
                        _proposedAllListenersList = null;
                    }

                    if (IsEmpty)
                    {
                        StopListening();
                    }
                }
                else
                {
                    // stop listening.  List cleanup is handled by Purge()
                    foundDirt = true;
                    StopListening();

                    foreach (DictionaryEntry de in _dict)
                    {
                        PropertyRecord pr = (PropertyRecord)de.Value;
                        pr.StopListening(_type);
                    }
                }

                return(foundDirt);
            }