当前位置: 首页 > 编程语言 > C#

尽管仍然强烈引用,C#WeakReference对象在终结器中为NULL分享

时间:2023-04-11 11:25:45 C#

C#学习教程:C#WeakReference对象在终结器中为NULL,尽管仍然被强引用评论)。这是Microsoft的一些我不知道或不理解的错误吗?该代码已在Debug中进行了测试,但我认为它不会改变任何内容。注意:您可以直接在控制台应用程序中测试代码。仅供参考...在supercat的回答之后,我用建议的解决方案修复了我的代码并且它运行得很好:-)!!!不好的是静态字典的使用及其性能,但它的工作原理。...几分钟后,我意识到SuperCat为我提供了解析静态字典的更好提示,我也这样做了。这是一个代码示例:错误代码已更正但带有静态ConditionalWeakTableConditioalWeakTable代码和SuperCat技巧(非常感谢他!)示例...使用系统;使用System.Collections.Generic;使用系统诊断;namespaceWeakrefBug{//*****************************************************************************B类:IDisposable{publicstaticListAllBs=newList();公共B(){AllBs.添加(这个);}privatebooldisposed=false;publicvoidDispose(){Dispose(真);GC.SuppressFinalize(这个);}protectedvirtualvoidDispose(booldisposing){if(!disposed){AllBs.Remove(this);处置=真;}}~B(){处置(假);}}//*************************************************************************A类{WeakReference_weakB=newWeakReference(newB());~A(){Bb=_weakB.TargetasB;if(b==null){if(B.AllBs.Count==1){Debugger.Break();//b仍然被引用,但我的弱引用找不到它,为什么?}}否则{b。处置();}}}//*************************************************************************类程序{staticvoidMain(string[]args){Aa=newA();一个=空;GC.Collect(GC.MaxGeneration);GC.WaitForPendingFinalizers();}}//*************************************************************************}版本更新:usingSystem;使用System.Collections.Generic;使用系统诊断;使用System.Runtime.CompilerServices;namespaceWeakrefBug//与ConditionalWeakTable一起正常工作{//****************************************************************************B类:IDisposable{publicstaticListAllBs=newList();publicB(){AllBs.Add(this);}privatebooldisposed=false;publicvoidDispose(){Dispose(真);GC.SuppressFinalize(这个);}protectedvirtualvoidDispose(booldisposing){if(!disposed){AllBs.Remove(this);处置=真;}}~B(){处置(假);}}//*************************************************************************A类{privatestaticreadonlySystem.Runtime.CompilerServices.ConditionalWeakTableWeakBs=newConditionalWeakTable();publicA(){WeakBs.Add(this,newB());}publicBCreateNewB(){Bb=newB();WeakBs.Remove(this);WeakBs.Add(this,b);返回b;}~A(){Bb;WeakBs.TryGetValue(this,outb);if(b==null){if(B.AllBs.Count==1){Debugger.Break();//B仍然被引用但是我的弱引用找不到它,为什么?}}else{b.Dispose();}}}//*************************************************************************类程序{staticvoidMain(string[]args){Aa=newA();WeakReferenceweakB=newWeakReference(a.CreateNewB());//通常不需要内部值,只是为了确保正确的功能a=null;GC.Collect(GC.MaxGeneration);GC.WaitForPendingFinalizers();Debug.Assert(!weakB.IsAlive);}}//*************************************************************************}包含SuperCat技巧的ConditioalWeakTable代码(非常感谢他!)usingSystem;使用System.Col选集.Generic;使用系统诊断;使用System.Runtime.CompilerServices;namespaceWeakrefBug//与非静态ConditionalWeakTable一起正常工作-自动清理{//****************************************************************************B类:IDisposable{publicstaticListAllBs=newList();publicB(){AllBs.Add(this);}privatebooldisposed=false;publicvoidDispose(){Dispose(真);GC.SuppressFinalize(这个);}protectedvirtualvoidDispose(booldisposing){if(!disposed){AllBs.Remove(this);处置=真;}}~B(){处置(假);}}//*************************************************************************A类{privateConditionalWeakTable_weakBs=null;publicA(){}publicBCreateNewB(){Bb=newB();if(_weakBs==null){_weakBs=newConditionalWeakTable();_weakBs.Add(b,_weakBs);}_weakBs.Remove(这个);_weakBs.Add(this,b);返回b;}internalConditionalWeakTableConditionalWeakTable//测试tOnly{得到{返回_weakBs;}}~A(){对象objB;_weakBs.TryGetValue(this,outobjB);if(objB==null){if(B.AllBs.Count==1){Debugger.Break();//B仍然被引用但是我的弱引用找不到它,为什么?}}else{((B)objB).Dispose();}}}//******************************************************************************类程序{staticvoidMain(string[]args){Aa=newA();WeakReferenceweakB=newWeakReference(a.CreateNewB());//通常不需要内部值,只是为了确保正确的功能WeakReferenceweakConditionalWeakTable=newWeakReference(a.ConditionalWeakTable);一个=空;GC.Collect(GC.MaxGeneration);GC.WaitForPendingFinalizers();Debug.Assert(!weakB.IsAlive);Debug.Assert(!weakConditionalWeakTable.IsAlive);}}//*****************************************************************************关于CitizenInsane的问题...我不记得我为什么要做我要做的事...我找到了我的样本,但当时不确定我的意思我试着弄明白了,有了下面的代码,我的东西就更清楚了,但还是想不起来我原来的需求了。对不起???使用系统;使用System.Collections.Generic;使用系统诊断;使用System.Runtime.CompilerServices;namespaceWeakrefBug//与ConditionalWeakTable一起正常工作{//****************************************************************************B类:IDisposable{publicstaticListAllBs=newList();publicB(){AllBs.Add(this);}privatebooldisposed=false;publicvoidDispose(){Dispose(真);GC.SuppressFinalize(这个);}protectedvirtualvoidDispose(booldisposing){if(!disposed){AllBs.Remove(this);处置=真;}}~B(){处置(假);}}//*************************************************************************A类{privateConditionalWeakTable_weakBs=null;私有弱引用_weakB=null;publicA(){_weakBs=newConditionalWeakTable();Bb=新B();_weakB=new弱引用(b);_weakBs.Add(b,_weakB);}publicBB{get{return_weakB.TargetasB;}设置{_weakB.Target=值;}}在ternalConditionalWeakTableConditionalWeakTable//TestOnly{get{return_weakBs;}}~A(){BobjB=B;if(objB==null){if(B.AllBs.Count==1){Debugger.Break();//B仍然被引用但是我的弱引用找不到它,为什么?}}else{((B)objB).Dispose();}}}//*************************************************************************类程序{staticvoidMain(string[]args){Test1();测试2();}privatestaticvoidTest1(){Aa=newA();WeakReferenceweakB=newWeakReference(aB);//通常不需要内部值,只是为了确保正确的功能WeakReferenceweakConditionalWeakTable=newWeakReference(a.ConditionalWeakTable);一个=空;GC.Collect(GC.MaxGeneration);GC.WaitForPendingFinalizers();Debug.Assert(B.AllBs.Count==0);GC.Collect(GC.MaxGeneration);GC.WaitForPendingFinalizers();Debug.Assert(!weakB.IsAlive);//需要收集第二遍CollectionDebug.Assert(!weakConditionalWeakTable.IsAlive);}privatestaticvoidTest2(){Aa=newA();WeakReferenceweakB=newWeakReference(aB);B.AllBs.Clear();aB=空;GC.Collect(GC.MaxGeneration);GC.WaitForPendingFinalizers();Debug.Assert(!weakB.IsAlive);//需要收集第二遍Collection}}//****************************************************************************}WeakReference有时令人讨厌的限制是WeakReference可能是如果WeakReference本身不存在强根引用,则无效,即使WeakReference的目标是强根引用,即使trackResurrection构造函数参数为true,也会发生这种情况。这种行为源于WeakReference有非托管资源(GC句柄),如果GC句柄没有被WeakReference的finalizer清除,将永远不会被清除,将构成内存泄漏。如果对象的终结器需要使用Wea??kReference对象,则该对象必须有一些配置以确保这些对象保持强引用。我不确定最佳模式是什么,但.net4.0中添加的ConditionalWeakTable可能会有用。它有点像字典,只是表本身是强引用的,并且给定一个键,其对应的值将被视为强引用。请注意,如果ConditionalWeakTable包含一个将X连接到Y并将Y连接到表的条目,那么只要X或Y保持不变,该表也将保持不变。垃圾回收有两个方面是您不能指望的:B.Dispose()方法中还有一个错误,当客户端代码显式处理对象时,它无法正确计算B实例。你还没有遇到那个错误。没有合理的方法来修复此代码。此外,它测试的内容已经得到CLR提供的硬性保证的支持。只需删除它。WeakReference_weakB可用于与对象a同时被垃圾回收。您在这里没有顺序保证,所以_weakB很可能在对象a之前完成。在A的终结器中访问_weakB是危险的,因为您不知道_weakB的状态。我猜你的情况已经完成了,这导致它为.Target返回null。以上就是C#学习教程:虽然还是强引用,但是C#的WeakReference对象在finalizer中是NULL。如果对你有用,需要了解更多C#学习教程,希望大家多加关注——本文来自网络收藏,不代表立场,如涉及侵权,请点击右转联系管理员删除。如需转载请注明出处:

最新推荐
猜你喜欢