过去 8 个月我们一直在使用 Xamarin iOS,并开发了一款具有许多屏幕、功能和嵌套控件的不平凡的企业应用程序。我们已经按照“推荐”完成了自己的 MVVM 架构、跨平台 BLL 和 DAL。我们在 Android 之间共享代码,甚至我们的 BLL/DAL 也用在我们的 Web 产品上。
一切都很好,只是现在在项目的发布阶段,我们发现基于 Xamarin iOS 的应用程序中到处都存在无法修复的内存泄漏。我们遵循所有“准则”来解决此问题,但实际情况是,C# GC 和 Obj-C ARC 似乎是不兼容的垃圾收集机制,因为它们在单触摸平台中彼此重叠。
我们发现的现实是本机对象和托管对象之间存在硬循环WILL发生并且频繁地对于任何重要的应用程序。例如,在使用 lambda 或手势识别器的任何地方,这种情况都很容易发生。再加上 MVVM 的复杂性,这几乎是一个保证。只要错过其中一种情况,整个对象图就永远不会被收集。这些图表会引诱其他对象进入并像癌症一样生长,最终导致 iOS 迅速而无情的消灭。
Xamarin 的回答是对问题的无私推迟和“开发人员应该避免这些情况”的不切实际的期望。仔细考虑这一点就会发现,这是承认Xamarin 中的垃圾收集本质上已被破坏.
我现在意识到,在 Xamarin iOS 中,您并没有真正获得传统 c# .NET 意义上的“垃圾收集”。您需要采用“垃圾维护”模式来实际让 GC 移动并完成其工作,即使这样它也永远不会完美 - 非确定性。
我的公司投入了大量资金试图阻止我们的应用程序崩溃和/或内存不足。我们基本上必须显式地、递归地处理所有可见的东西,并在应用程序中实施垃圾维护模式,只是为了阻止崩溃并拥有我们可以销售的可行产品。我们的客户是支持和宽容的,但我们知道这不可能永远持续下去。我们希望 Xamarin 有一个专门的团队来解决这个问题并一劳永逸地解决它。不幸的是,看起来并不像。
问题是,对于用 Xamarin 编写的重要企业级应用程序来说,我们的经验是例外还是规则?
UPDATE
请参阅 DisposeEx 方法和解决方案的答案。
我已经发布了一个用 Xamarin 编写的重要应用程序。许多其他人也有同样的经历。
“垃圾收集”并不是魔法。如果您创建一个附加到对象图的根的引用并且从未将其分离,则它将不会被收集。这不仅适用于 Xamarin,也适用于 .NET、Java 等上的 C#。
button.Click += (sender, e) => { ... }
是一种反模式,因为您没有对 lambda 的引用,并且您永远无法从 lambda 中删除事件处理程序Click
事件。同样,在托管和非托管对象之间创建引用时,您必须小心地了解自己在做什么。
至于“我们已经完成了自己的 MVVM 架构”,有一些高调的 MVVM 库(MVVM交叉 https://github.com/MvvmCross/MvvmCross, 反应式用户界面 http://www.reactiveui.net/, and MVVM 轻型工具包 https://mvvmlight.codeplex.com/),所有这些都非常重视参考/泄漏问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)