Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I fix the GC cycle caused by a lambda event handler?

Watching Advanced Memory Management by Mark Probst and Rodrigo Kumpera, I learned new techniques such as profiling Mono GC and using WeakReference.

Yet I still don't understand how to “fix” the Puzzle 2 from 28th minute:

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 ();
    }
}

The controller holds a ref to button that holds a ref to event handler that holds a ref to the controller.

One way to break the cycle would be to nullify the button. Another way is to detach the handler (but we'd have to forsake using lamdas).

Are there other /more elegant/ ways to break the cycle? Can we somehow stick WeakReference in here?

Thanks.

Edit: In this case, the button is not even a field. But there is still a cycle, isn't there? It's in Controller's View's Subviews. Do we have to clear them? I'm confused.

like image 877
Dan Abramov Avatar asked Jun 14 '13 10:06

Dan Abramov


People also ask

How do I fix Lambda throttling?

Check the setting using the Lambda console, or by calling the GetFunction API. Note: If a function is configured to have zero reserved concurrency, then the function is throttled because it can't process any events. Make sure that you increase the value to a number greater than zero.

How do I troubleshoot Lambda function failures?

To troubleshoot Lambda code errors You can use CloudWatch to view all logs generated by your function's code and identify potential issues. For more information, see Accessing Amazon CloudWatch Logs for AWS Lambda.

How do you change the Lambda handler?

This function handler name reflects the function name ( lambda_handler ) and the file where the handler code is stored ( lambda_function.py ). To change the function handler name in the Lambda console, on the Runtime settings pane, choose Edit.


1 Answers

Cycles are not usually a problem in a garbage-collected environment - I must assume from the question that this is somehow different in monotouch? Edit: no, my assumption here remains valid - at 7:50 in the video you link to it demonstrates a cycle being discarded by the "sweep".

Cycles can usually be ditched whole-sale, as soon as the entire cycle becomes unreachable. This would be a problem in a reference-counted system.

However! With regards your question - does the button (once added) know about the controller? if so, you could get there from sender:

button.TouchUpInside += (sender, e) =>
            ((UIButton)sender).Parent.RemoveFromParentViewController();

This lambda now doesn't involve a captured variable, and doesn't involve a capture context; it doesn't hold any reference to the controller - and actually most compilers will make that a single static handler rather than a handler per usage, so it is more efficient in terms of delegate creations too.


Re the context of monotouch specifically, then yes, you'd need to use WeakReference<T>:

var controller = new WeakReference<Puzzle2Controller>(this);
button.TouchUpInside += (sender, e) => {
    var parent = controller.Object;
    if(parent != null) parent.RemoveFromParentViewController();
};
like image 192
Marc Gravell Avatar answered Sep 29 '22 22:09

Marc Gravell