Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke Action created from Expression<Action> in another scope

Consider the following simple example:

private Action _action;

public Form1() { InitializeComponent(); }

private void button1_Click(object sender, EventArgs e)
{
    string msg = "test";
    Expression<Action> exp = () => MessageBox.Show(msg);
    _action = exp.Compile();
    msg = "testC";
}

private void button2_Click(object sender, EventArgs e)
{
    _action();
}

When button2 is clicked, I see testC.

My question is:

I want to store actions to be run later. Can I safely store the delegate that compile() creates and use it whenever I want?

My question is mostly about method arguments. I am not aware on how they are stored (by ref or by value), of if they can they be cleared by GC in the meantime. In general I doubt that this is the correct approach. Also, msdn isn't of much help.

I am creating a JobManager that supports High priority actions to be executed. There is a stack of default actions and some high priority that need to be added. This part is where I register the high priority job (using a lambda -> get the method -> create delegate -> store it -> run in when needed). I am not sure if this is the right approach to store the action anyway.

like image 763
Odys Avatar asked Nov 30 '25 18:11

Odys


1 Answers

Yes, you can.
The lambda expression creates a closure that holds references to the local variables that it uses from the outer function.

This closure is referenced in the delegate's Target property.
As long as you hold a reference to the delegate, those variables won't be GC'd.

For a more detailed look at how this works, see my blog post.

like image 69
SLaks Avatar answered Dec 03 '25 09:12

SLaks



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!