如果垃圾收集器在Monotouch 4中“更具攻击性”,这意味着什么?

时间:2011-08-18 19:39:45

标签: .net mono garbage-collection xamarin.ios boehm-gc

我偶然发现了这个问题:Button in ContentView causes crash in MonoTouch runtime. Bug in Monotouch 4.0?并且询问者在Monotouch的“更具侵略性”的垃圾收集器方面存在问题。

  • 有人可以解释为什么在询问者的情况下会发出错误(会收集什么以及为什么?)?
  • “更具攻击性”是什么意思?我可以陷入什么陷阱?我应该避免什么?
  • 关于iOS5:Apple声称使用iOS5,该应用程序将获得一个内存警告,然后它将被杀死。与之前的任何其他版本不同,应用程序收到三个警告。这对Monotouch意味着什么?它将如何处理这种行为?

也许其中一个Xamarin团队可以总结一些注意事项并给出一个很好的解释?

我目前正在从MT 3.2.6升级到MT 4.1,并希望查看我的代码并检查需要更改的内容。

5 个答案:

答案 0 :(得分:6)

我们发现,有时开发人员会遇到奇怪的问题,比如对话框有时会停留在屏幕上,有时它们会消失而不会留下痕迹,也没有解释为什么会发生这种情况。

这通常发生在您创建UIAlertView并且没有对其进行引用时,因此就MonoTouch而言,该对象是垃圾(您没有从代码中引用它,因此您没有使用它) 。

但是,对话框是否立即或稍后从屏幕上消失,取决于垃圾收集器的启发式方法是否确定是时候运行集合了。如果您刚刚在收集后创建了一个对话框,则可能是您的对话框将保留在屏幕上。但是如果你非常接近某个集合,或者你有一个后台进程消耗内存,那么就会触发GC。

这通常让用户感到困惑,“为什么事情会随机消失”。答案是:如果你没有提到它,那么GC就假设你不在乎。

为了让我们的用户更清楚,在模拟器上以调试模式运行MonoTouch时(并且有一个命令行选项可以控制任何版本),我们在模拟器上添加了一个连续调用GC.Collect的线程()每隔几秒钟。这使得您可能没有保留对您的对话框的引用更为明显。

后来,我们发现一个非常有用和常见的模式是保持两种对话框,除了它们的副作用之外没有任何用处:UIAlertView和UIActionSheet。我们改变了MonoTouch,以便在内部保留对这两者的引用,直到被解雇。

所以我们最终得到了两个世界中最好的:在开发周期中你捕获了早期缺少对你需要的对象的引用,我们处理了两个最常见的只对它们的副作用有用的情况。

答案 1 :(得分:1)

这是很多好问题。

关于侵略性,垃圾收集器可以收集对象,一旦没有对象的引用。如果它缓慢地执行此操作(称为被动),您可能从未注意到您的软件中存在一些错误。

OTOH在低内存条件下运行应用程序(多任务处理)带来了它自身的问题。因此,更频繁地收集(称为积极的)将更快地回收内存并且可以帮助整体性能。但是,如果在没有托管引用之后仍然使用对象,则更有可能命中(您自己的)错误

答案 2 :(得分:1)

所以在阅读完代码之后,我找不到为什么会出现这个问题(而且没有足够的代码可以快速尝试)。现在如果崩溃与UIButton有关,那么AddSubView应该在逻辑上做出引用。阅读documentation证实了这一点(重点是我的):

  

要添加的视图。 此视图由接收方保留。添加后,此视图将显示在任何其他子视图的顶部。

一些谷歌搜索让我到bug #670294链接到stackoverflow question非常类似于你链接的那个。注释#22描述了此问题的解决方法(这是一个错误)并在MonoTouch 4.1中得到修复。

现在我无法告诉你这是影响MonoTouch本身的GC问题(同样的规则适用于所有人)或无关。我会猜测它是相关的,因为保留另一个参考被引用作为解决方案 - 但是因为我很好奇我会看一下修复并稍后添加评论 ;-)

答案 3 :(得分:0)

我是那个说GC“更具侵略性”的人。这就是我的用语 - 我认为Miguel认为它有点不同。我的解释是基于这样一个事实,即你在MT3中可以逃脱的东西在MT4中不再起作用(或者不那么可靠)。

答案 4 :(得分:0)

另一个答案......

  

关于iOS5:Apple声称iOS5应用程序将获得一个   记忆警告,然后它会被杀死。与任何其他版本不同   之前,应用程序收到三个警告。这意味着什么   MonoTouch的?它将如何处理这种行为?

我不会谈论iOS5(因为我不跟踪什么是公开的,什么不是)。既然你不知道内存有多低(或其他东西需要),那么拥有非常复杂的内存释放策略是没有意义的。用户需要其他地方,将其退回:)

解决这个问题的方法是覆盖 DidReceiveMemoryWarning 并免费提供一切,例如:

  • 致电GC.Collect() - 这是为数不多的,恰当的时间致电此事;
  • 清除您拥有的所有缓存(例如,下载的数据,以后可以在需要时重新计算的任何其他内容)