Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/267.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何修复lambda事件处理程序导致的GC循环?_C#_Mono_Xamarin.ios_Garbage Collection_Xamarin - Fatal编程技术网

C# 如何修复lambda事件处理程序导致的GC循环?

C# 如何修复lambda事件处理程序导致的GC循环?,c#,mono,xamarin.ios,garbage-collection,xamarin,C#,Mono,Xamarin.ios,Garbage Collection,Xamarin,在MarkProbst和RodrigoKumpera的观看下,我学习了一些新技术,比如分析MonoGC和使用WeakReference 但我仍然不明白如何从第28分钟开始“修复”谜题2: public class CustomButton : UIButton { public CustomButton () { } } public class Puzzle2Controller : UIViewController { public override void ViewDi

在MarkProbst和RodrigoKumpera的观看下,我学习了一些新技术,比如分析MonoGC和使用
WeakReference

但我仍然不明白如何从第28分钟开始“修复”谜题2:

public class CustomButton : UIButton {
    public CustomButton () { }
}

public class Puzzle2Controller : UIViewController
{
    public override void ViewDidLoad ()
    {
        var button = new CustomButton ();
        View.Add (button);
        button.TouchUpInside += (sender, e) =>
            this.RemoveFromParentViewController ();
    }
}
控制器持有一个ref to按钮,该按钮持有一个ref to事件处理程序,该事件处理程序持有控制器的ref

打破这种循环的一种方法是取消按钮。 另一种方法是分离处理程序(但我们不得不放弃使用lamdas)

是否有其他/更优雅的/打破循环的方法?我们能把
WeakReference
放在这里吗

谢谢

编辑:在这种情况下,按钮甚至不是字段。但还是有一个循环,不是吗?它位于控制器视图的子视图中。我们必须清理它们吗?我很困惑。

在垃圾收集环境中,循环通常不是一个问题-我必须从这个问题假设,在monotouch中,这在某种程度上是不同的?编辑:不,我在这里的假设仍然有效-在你链接到它的视频中,7:50演示了一个被“扫描”丢弃的循环

一旦整个销售周期变得遥不可及,通常可以放弃整个销售周期。在参考计数系统中,这将是一个问题

然而!关于您的问题-按钮(一旦添加)是否了解控制器?如果是这样,您可以从
发送者那里到达:

button.TouchUpInside += (sender, e) =>
            ((UIButton)sender).Parent.RemoveFromParentViewController();
这个lambda现在不涉及捕获的变量,也不涉及捕获上下文;它不包含对控制器的任何引用——实际上,大多数编译器都会使用单个静态处理程序,而不是每次使用一个处理程序,因此它在委托创建方面也更有效


具体来说,是monotouch的上下文,那么是的,您需要使用
WeakReference

var控制器=新的WeakReference(此);
button.TouchUpInside+=(发送者,e)=>{
var parent=controller.Object;
如果(parent!=null)parent.RemoveFromParentViewController();
};

您好,谢谢您的回复。这当然是一个选项,但不幸的是,
UIView
s没有保存对其控制器的引用。如果我的理解是正确的,MonoTouch中的循环是一个问题,因为在引擎盖下,原生ObjC对象使用引用计数。(见21:30)谢谢!这完全有道理。@MarcGravel:如果循环被“扫描”丢弃,那么在上述情况下我们还必须使用WeakReference吗?
var controller = new WeakReference<Puzzle2Controller>(this);
button.TouchUpInside += (sender, e) => {
    var parent = controller.Object;
    if(parent != null) parent.RemoveFromParentViewController();
};