gpt4 book ai didi

c# - ConditionalWeakTable - GC.Collect() 行为,为什么它没有按预期运行?

转载 作者:行者123 更新时间:2023-12-05 09:26:10 26 4
gpt4 key购买 nike

为什么我的 weakRef.Target 在第二次射击时还活着?

会不会是bug?如果不是,错误在哪里?

结果:

weakRef.Target is alive = True, expected true because inst keep a hold on SomeClass.
weakRef.Target is alive = True, expected false, because there is no more ref on SomeClass.

代码:

public static class DelegateKeeper
{
private static ConditionalWeakTable<object, Action> cwtAction = new ConditionalWeakTable<object, Action>();
public static void KeepAlive(Action action) => cwtAction.Add(action.Target, action);
}

public class SomeClass
{
public void DoSomething() { }
}

public static class GcHelper
{
public static void Collect()
{
// OK surely overkill but just to make sure. I will reduce it when everyting will be understood.
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();
}
}

SomeClass instanceSomeClass;
WeakReference<Action> weakRef;

[TestMethod]
public void TestLifeOfObject()
{
Init();
GcHelper.Collect();
Debug.WriteLine($"weakRef.Target is alive = {weakRef.TryGetTarget(out _)}, expected true because inst keep a hold on SomeClass.");

RemoveLastReferenceOnSomeClass();
GcHelper.Collect();
Debug.WriteLine($"weakRef.Target is alive = {weakRef.TryGetTarget(out _)}, expected false, because there is no more ref on SomeClass.");
}

private void Init()
{
instanceSomeClass = new SomeClass();
var action = instanceSomeClass.DoSomething;
weakRef = new WeakReference<Action>(action);
DelegateKeeper.KeepAlive(action);
}

private void RemoveLastReferenceOnSomeClass()
{
instanceSomeClass = null;
}

最佳答案

documentation对此尚不清楚,但 ConditionalWeakTable 似乎确实持有对要添加的 value 的强引用,即使 key 仅持有弱引用。

浏览the source code ,它使用了 DependentHandle,文档中说:

A DependentHandle value with a given object instance as target will not cause the target to be kept alive if there are no other strong references to it, but it will do so for the dependent object instance as long as the target is alive.

因此,因为您添加了 action 作为值,而 action lambda 本身捕获了 inst,因此您正在对安装

虽然您可以存储其他对象,但您不关心是否有字符串引用。参见 this fiddle其中 new object() 被存储为值,并且它可以正常工作。我不知道你的用例,所以我不知道这是否适合你。

但我也会注意到 Microsoft state :

Avoid using weak references as an automatic solution to memory management problems. Instead, develop an effective caching policy for handling your application's objects.

关于c# - ConditionalWeakTable - GC.Collect() 行为,为什么它没有按预期运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74216108/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com