public void EnumerationCleaning() { var c = new WeakCollection <object>(); object x = new object(); using (NoGCRegion.Enter(1000)) { c.Add(x); c.Add(x); c.Add(x); AddCollectableItems(c, 3); Assert.AreEqual(6, c.AddCountSinceLastClean); Assert.AreEqual(6, c.UnsafeCount); } Helpers.CollectAndWait(); foreach (object o in c) { } Assert.IsTrue(c.Remove(x)); Assert.IsTrue(c.Remove(x)); #if NETCOREAPP2_2 // NS2.0 target does not support removing stale entries as items are encountered. Assert.AreEqual(6, c.AddCountSinceLastClean); Assert.AreEqual(4, c.UnsafeCount); #else Assert.AreEqual(0, c.AddCountSinceLastClean); Assert.AreEqual(1, c.UnsafeCount); #endif GC.KeepAlive(x); }
public void WeakCollection() { "添加元素,但只有 1 个被强引用,于是 GC 后只剩 1 个元素。".Test(() => { // Arrange var collection = new WeakCollection <object>(); // Action collection.Add(new object()); var a = new object(); collection.Add(a); GC.Collect(); // Assert Assert.AreEqual(1, collection.TryGetItems(x => true).Length); }); "移除元素,被强引用的元素也被移除,于是 GC 后没有元素了。".Test(() => { // Arrange var collection = new WeakCollection <object>(); // Action collection.Add(new object()); var a = new object(); collection.Add(a); collection.Remove(a); GC.Collect(); // Assert Assert.AreEqual(0, collection.TryGetItems(x => true).Length); }); }
public void RemoveWorksAfterCollect() { var arr = new[] { "a", "b" }; var wc = new WeakCollection <string>(arr); { wc.Add(new string('c', 1)); wc.Add(new string('d', 1)); wc.Add(new string('c', 1)); } GCEx.CollectAndWait(); Assert.False(wc.Remove("c")); Assert.False(wc.Remove("d")); Assert.True(wc.SequenceEqual(new[] { "a", "b" })); }
public void AddWorksAfterCollect() { var wc = new WeakCollection <string>(); { wc.Add(new string('a', 1)); Assert.Equal("a", wc.First()); } GCEx.CollectAndWait(); Assert.True(wc.CapCount <= 1); //Assert.Equal(0, wc.Count); wc.Add(new string('b', 1)); Assert.Equal(1, wc.Count); Assert.Equal("b", wc.First()); }
/// <summary> /// 创建一个 <typeparamref name="T"/> 的实例,加入到集合中,然后将此实例返回。 /// 必须调用这个方法创建并返回,否则你无法说明没释放是因为局部变量引用还是因为被测代码有问题,详见:https://github.com/dotnet/runtime/issues/36265 /// </summary> /// <typeparam name="T">要创建的实例的类型。</typeparam> /// <param name="collection">创建的实例加入到这个集合中。</param> /// <returns>创建的新实例。</returns> private static object AddNewObjectAndReturn <T>(WeakCollection <T> collection) where T : class, new() { var t = new T(); collection.Add(t); return(t); }
private static void AddCollectableItems(WeakCollection <object> c, int count) { for (int i = 0; i < count; i++) { c.Add(new object()); } }
//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- #endregion //-------------------------------------------------------------- #region Methods //-------------------------------------------------------------- /// <summary> /// Registers the specified resource pool. /// </summary> /// <param name="pool">The resource pool to register.</param> internal static void Register(ResourcePool pool) { lock (PoolsInternal) { PoolsInternal.Add(pool); } }
private static void UpdateScrollBarStyles(FrameworkElement element) { if (element is null) { throw new ArgumentNullException(nameof(element)); } var themeScrollBars = GetThemeScrollBars(element); if (themeScrollBars.HasValue) { SetScrollBarStyles(element, themeScrollBars.Value); if (themeScrollBars.Value) { WeakUnthemedScrollingElements.Remove(element); } else { WeakUnthemedScrollingElements.Add(element); } } else { RemoveScrollBarStyles(element); WeakUnthemedScrollingElements.Remove(element); } }
/// <summary> /// Subscribes an observer to the subject. /// </summary> /// <param name="observer"> /// The <see cref="IObserver{T}"/> to subscribe to the subject. /// </param> /// <remarks> /// An <see cref="IDisposable"/> object that can be used to unsubscribe the observer from /// the subject. /// </remarks> public IDisposable Subscribe(IObserver <T> observer) { if (observer == null) { throw new ArgumentNullException(nameof(observer)); } lock (_gate) { ThrowIfDisposed(); if (_observers != null) { _observers.Add(observer); return(new Subscription(this, observer)); } else { // Subject is stopped. if (_error != null) { observer.OnError(_error); } else { observer.OnCompleted(); } return(Disposable.Empty); } } }
private void AllocateWithDual <TItem>(out WeakCollection <TItem> collection, out TItem item1, out TItem item2, int count) where TItem : class, new() { //**************************************** var Items = new TItem[count]; //**************************************** for (var Index = 0; Index < count; Index++) { Items[Index] = new TItem(); } collection = new WeakCollection <TItem>(); collection.AddRange(Items); collection.Add(item1 = new TItem()); collection.Add(item2 = new TItem()); }
public void CopyToWorksAfterCollect() { var arr = new[] { "a", "b" }; var wc = new WeakCollection <string>(arr); { wc.Add(new string('c', 1)); wc.Add(new string('d', 1)); } GCEx.CollectAndWait(); var target = new string[5]; wc.CopyTo(target, 1); Assert.True(arr.SequenceEqual(target.Skip(1).Take(2))); Assert.Null(target[0]); Assert.Null(target[3]); Assert.Null(target[4]); }
public void Purge() { var weakCollection = new WeakCollection <object>(); var list = new List <object>(); object obj; for (int i = 0; i < 100; i++) { obj = i; list.Add(obj); weakCollection.Add(obj); } obj = null; for (int i = list.Count - 1; i >= 0; i--) { if (i % 2 == 0 || i % 3 == 0) { list.RemoveAt(i); } } GC.Collect(); int index = 0; foreach (object item in weakCollection) { // Because of compiler/JIT optimization: The last element "99" might be // still be referenced by local variable and can't be purged. if (index == list.Count) { continue; } Assert.AreEqual(list[index], item); index++; } // WeakCollection<T> should be purged/compacted now. // --> Check again. index = 0; foreach (object item in weakCollection) { // Because of compiler/JIT optimization: The last element "99" might be // still be referenced by local variable and can't be purged. if (index == list.Count) { continue; } Assert.AreEqual(list[index], item); index++; } }
public void ContainsWorksAfterCollect() { var arr = new[] { "a", "b" }; var wc = new WeakCollection <string>(arr); { wc.Add(new string('c', 1)); wc.Add(new string('d', 1)); Assert.True(wc.Contains("a")); Assert.True(wc.Contains("b")); Assert.True(wc.Contains("c")); Assert.True(wc.Contains("d")); } GCEx.CollectAndWait(); Assert.True(wc.Contains("a")); Assert.True(wc.Contains("b")); Assert.False(wc.Contains("c")); Assert.False(wc.Contains("d")); Assert.False(wc.Contains("e")); }
internal static void AddAnchor(PermanentAnchor anchor) { permanentAnchors.Add(anchor); IDocument doc; if (openDocuments.TryGetValue(anchor.FileName, out doc)) { anchor.AttachTo(doc); } }
internal void Add(Texture2D reference, ScaledTexture texture, Bounds source, int expectedScale) { lock (reference.Meta()) { var Map = reference.Meta().SpriteTable; var rectangleHash = SpriteHash(texture: reference, source: source, expectedScale: expectedScale); using (Lock.Exclusive) { ScaledTextureReferences.Add(texture); Map.Add(rectangleHash, texture); } } }
public void RegisterGraphContext(IGraphContext context) { lock (_lock) { if (!_expandedGraphContexts.Contains(context)) { // Remember this graph context in order to track changes. // When references change, we will adjust children of this graph as necessary _expandedGraphContexts.Add(context); } } }
internal void Add(Texture2D reference, ScaledTexture texture, Bounds source, uint expectedScale) { var rectangleHash = SpriteHash(texture: reference, source: source, expectedScale: expectedScale); var meta = reference.Meta(); using (Lock.Exclusive) { ScaledTextureReferences.Add(texture); using (meta.Lock.Exclusive) { meta.SpriteTable.Add(rectangleHash, texture); } } }
//-------------------------------------------------------------- #region Creation & Cleanup //-------------------------------------------------------------- /// <summary> /// Initializes a new instance of the <see cref="CameraNode"/> class. /// </summary> /// <param name="camera">The camera.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="camera"/> is <see langword="null"/>. /// </exception> public CameraNode(Camera camera) { if (camera == null) { throw new ArgumentNullException("camera"); } _camera = camera; Shape = camera.Projection.ViewVolume; // Register camera node in global list. Instances.Add(this); }
public void Add() { var MyCollection = new WeakCollection <object>(); var MyObject = new object(); MyCollection.Add(MyObject); GC.Collect(); Assert.AreEqual(1, MyCollection.Count(), "Item was not added"); GC.KeepAlive(MyObject); }
public void ClearWorksAfterCollect() { var wc = new WeakCollection <string>(); { var a = new string('a', 1); wc.Add(a); Assert.Equal("a", wc.First()); } GCEx.CollectAndWait(); wc.Clear(); Assert.Equal(0, wc.CapCount); Assert.False(wc.Any()); }
/// <summary> /// 確保されたメモリにアクセスする <see cref="UnmanagedMemoryStream"/> を作成します。 /// </summary> /// <returns>確保されたメモリにアクセスする <see cref="UnmanagedMemoryStream"/>。</returns> public UnmanagedMemoryStream CreateStream() { if (IsClosed || IsInvalid) { throw new ObjectDisposedException(ToString()); } lock (streams) { var stream = new UnmanagedMemoryStream(this, 0, (long)ByteLength, FileAccess.ReadWrite); streams.Add(stream); return(stream); } }
internal static IEnumerable <UIElement> GetSortedNavigableControls() { if (IsCommandNavigationOrderDirty) { var list = NavigableControls.OrderBy(GetCommandNavigationOrder).ToList(); NavigableControls.Clear(); foreach (var uiElement in list) { NavigableControls.Add(uiElement); } IsCommandNavigationOrderDirty = false; } return(NavigableControls); }
public void Clean() { var c = new WeakCollection <object>(); object x = new object(); using (NoGCRegion.Enter(1000)) { c.Add(x); c.Add(x); c.Add(x); AddCollectableItems(c, 3); Assert.AreEqual(6, c.AddCountSinceLastClean); Assert.AreEqual(6, c.UnsafeCount); } Helpers.CollectAndWait(); c.Clean(); Assert.AreEqual(0, c.AddCountSinceLastClean); Assert.AreEqual(3, c.UnsafeCount); GC.KeepAlive(x); }
/// <inheritdoc/> protected override UIElement OnGetLegendSymbol() { // The symbol for the normal legend is miniature version of the pie chart. // The legend symbol is automatically updated in OnUpdate()! var canvas = new Canvas { Width = 16, Height = 16, }; // Store legend symbol using weak reference. // (The symbol is drawn in OnUpdate().) _legendSymbols.Add(canvas); return(canvas); }
public void RegisterHandler(IChangedHandler handler) { lock (this) { if (_handlers == null) { _handlers = new WeakCollection <IChangedHandler>(); _handlers.CleanedEvent += (sender, e) => { lock (this) if (_handlers.Count == 0) { _handlers = null; } }; } _handlers.Add(handler); } }
/// <summary> /// Creates a new child container. /// </summary> /// <returns>The child container.</returns> public ServiceContainer CreateChildContainer() { ThrowIfDisposed(); var childContainer = OnCreateChildContainer(); if (childContainer != null) { // Set parent. childContainer._parent = this; // Keep track of child container. lock (_childContainers) { _childContainers.Add(childContainer); } } return childContainer; }
internal async Task BeginGetGraphDataAsync(IGraphContext context) { try { await InitializeAsync(); bool shouldTrackChanges = false; foreach (Lazy <IDependenciesGraphActionHandler, IOrderPrecedenceMetadataView> handler in _graphActionHandlers) { if (handler.Value.CanHandleRequest(context) && handler.Value.HandleRequest(context)) { shouldTrackChanges = true; break; } } if (!shouldTrackChanges) { return; } lock (_expandedGraphContexts) { if (!_expandedGraphContexts.Contains(context)) { // Remember this graph context in order to track changes. // When references change, we will adjust children of this graph as necessary _expandedGraphContexts.Add(context); } } } finally { // OnCompleted must be called to display changes context.OnCompleted(); } }
public static void RegisterMainToolBarTray(ToolBarTray tray) { MainToolBarTrays.Add(tray); }
/// <summary> /// 创建一个 <typeparamref name="T"/> 的实例,然后加入到集合中。 /// 必须调用这个方法创建,避免创建的局部变量被视为不能释放,详见:https://github.com/dotnet/runtime/issues/36265 /// </summary> /// <typeparam name="T">要创建的实例的类型。</typeparam> /// <param name="collection">创建的实例加入到这个集合中。</param> private static void AddNewObject <T>(WeakCollection <T> collection) where T : class, new() => collection.Add(new T());
public static void RegisterMenu(Controls.Menu.Menu menu) { MainMenus.Add(menu); }
public void Purge() { var weakCollection = new WeakCollection<object>(); var list = new List<object>(); object obj; for (int i = 0; i < 100; i++) { obj = i; list.Add(obj); weakCollection.Add(obj); } obj = null; for (int i = list.Count - 1; i >= 0; i--) { if (i % 2 == 0 || i % 3 == 0) list.RemoveAt(i); } GC.Collect(); int index = 0; foreach (object item in weakCollection) { // Because of compiler/JIT optimization: The last element "99" might be // still be referenced by local variable and can't be purged. if (index == list.Count) continue; Assert.AreEqual(list[index], item); index++; } // WeakCollection<T> should be purged/compacted now. // --> Check again. index = 0; foreach (object item in weakCollection) { // Because of compiler/JIT optimization: The last element "99" might be // still be referenced by local variable and can't be purged. if (index == list.Count) continue; Assert.AreEqual(list[index], item); index++; } }
public void TestBasics() { WeakCollection<object> c = new WeakCollection<object>(); c.Add(new object()); c.Add(new object()); c.Add(new object()); c.Add(new object()); c.Add(this); Assert.AreEqual(5, c.Count); Assert.IsTrue(c.Contains(this)); int n = 0; foreach (object o in c) { Assert.IsTrue(o.GetType() == typeof(object) || o.GetType() == this.GetType()); n++; } Assert.AreEqual(5, n); GC.Collect(); GC.WaitForPendingFinalizers(); Assert.AreEqual(1, c.Count); Assert.IsTrue(c.Contains(this)); n = 0; foreach (object o in c) { Assert.IsTrue(o.GetType() == this.GetType()); Assert.IsTrue(o == this); n++; } Assert.AreEqual(1, n); c.CopyTo(new object[1], 0); }