2

After following this question on updating a GUI from another thread I wanted to extend the code slightly so that it worked for something other than property assignment. Specifically I was trying to find a way to assign some functionality directly to a lambda so that I can define the behavior as needed (I modified the original slightly for WPF):

    private delegate void UpdateControlThreadSafeDelegate(Control control, System.Linq.Expressions.Expression<Action> property);
    public void UpdateControl(Control control, System.Linq.Expressions.Expression<Action> property)
    {

        // If calling thread is not associated with control dispatcher, call our thread safe property update delegate
        if (!control.Dispatcher.CheckAccess())
        {
            control.Dispatcher.Invoke(new UpdateControlThreadSafeDelegate(UpdateControl), new object[] { control, property });
        }
        else
        {
            Action call = property.Compile();
            call();
        }
    }

With usage:

UpdateControl(lbFoo, () => lbFoo.Items.Clear()); // where lbFoo is a ListBox control

This works fine. But I'd rather allow do something like:

UpdateControl(lbFoo, () => { lbFoo.Items.Clear(); lbFoo.Items.Add("Bar");});

This does not work, returning error CS0834: A lambda expression with a statement body cannot be converted to an expression tree. The error is clear, I'm just not certain on how best to proceed. I could follow my original usage and do what I need in several lines, it's just not as tidy.

I'm guessing there is a better/easier way to do what I want.

Community
  • 1
  • 1
Jerdak
  • 3,997
  • 1
  • 24
  • 36

1 Answers1

5

If you don't use expressions, and just pass the action, like so:

public void UpdateControl(Control control, Action actionToExecute)

Then you can use this as written. The only other change will be your else statement, where you would just call this directly:

   else
    {
        actionToExecute();
    }
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373