首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么时候才能使用(新的SomeThing()) { ... }安全地GC已分配但未命名的资源?

什么时候才能使用(新的SomeThing()) { ... }安全地GC已分配但未命名的资源?
EN

Stack Overflow用户
提问于 2016-03-03 03:50:30
回答 1查看 81关注 0票数 1

我修复了我的Vsync库(以前被称为Isis2)中的一个bug,它集中在我和Mono之间在using子句的语义上的分歧。在Vsync中,我有提升线程优先级的锁包装器,以避免优先级反转(高优先级线程可能正在等待低优先级线程持有的锁)。代码如下所示:

代码语言:javascript
复制
using(new LockAndElevate(myLock)) { ... code protected by myLock ... }

我的理解是,这完全等同于

代码语言:javascript
复制
try { ml = new LockAndElevate(myLock)); ... code ... } finally { ml.Dispose(); }

但实际上,mono垃圾收集器似乎得出结论,在我的受保护代码中没有对锁定对象的引用(第一个示例中没有使用变量),垃圾收集器在“受保护”的代码块中收集它。当我将代码更改为:

代码语言:javascript
复制
using(var tmp = new LockAndElevate(myLock)) { ... code ... }

因此,通过添加一个我从未引用过的变量,我可以防止过早的GC。但是在语义上,他们应该能够进行代码分析,并意识到tmp变量没有被引用,删除"var tmp =“部分,这时他们可能会再次错误地过早地收集我包装的锁。因此,我的修复让我担心,因为将来对Mono的编译器改进可能会再次打破这一逻辑。

是我错了,还是这是一个单声道编译器错误?

EN

回答 1

Stack Overflow用户

发布于 2016-03-04 00:50:48

好吧,对于那些将来可能会读到这篇文章的人,我将总结一下人们一直在说的话:

  • @EricLippert认为我的编码风格与"using“语句的意图不同,因此存在风险。他建议使用(丑陋的)方法,使用显式变量保存新资源,然后使用try-finally语句,这显然是安全的,correct.
  • @CodeCaster指出了微软自己的人一直在使用与我相同的代码风格的情况(像我一样,他们利用Dispose来触发清理操作)。@EricLippert希望他们先检查一下他。
  • .NET C#编译器显然不会垃圾回收资源,直到应用程序退出using语句,而我观察到Mono编译器这样做(但没有最小的可重现示例,这对所有相关人员都是令人沮丧的)。但从某种意义上讲,这两种行为都符合C#规范。在一个似乎已被删除的子线程中,有人指出C#规范似乎不鼓励我使用的编码风格,尽管微软内部人员也以同样的方式使用“使用”。
  • 可以认为在这方面该规范是不正确的。基本上,一个写得很好的编译器会检测并修剪死代码。因此,编译器可能会注意到using语句中分配的资源并未实际使用(无论您是否声明了临时变量,都可能会这样做),清理代码,并最终得出using语句本身可以安全删除的结论。这两个示例--我的示例中有锁定副作用,以及ASP.NET示例中的内部块创建了一个网页,finally语句将该页面写入输出流--说明了这种推理中的缺陷。根据Dispose
  • 的说法,using语句实际上不应该要求使用临时变量命名资源,也不应该要求代码使用引用:由于副作用,应该将资源本身视为由using代码块引用,并且在代码块终止之前不能安全地进行垃圾回收,因为这可能过早地触发

()操作。

我希望我的总结是正确的。为了我自己的目的,我可能会采纳埃里克的建议。另一方面,这使得一段优雅的代码变得非常丑陋,事实证明,只需分配一个临时变量,虽然有点丑陋,但确实解决了问题(目前)。另外,正如上面所解释的,C#规范本身可能需要在这一特定方面进行发展,因此,Mono行为很可能会被声明为“不正确”。因此,也许我还不会让我的代码变得非常粗俗和令人厌恶!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35756775

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档