Help with understanding C# syntax while Invoking a new Action

19,020

Solution 1

This uses something known as a "lambda expression" to create an anonymous delegate that matches the signature expected by the Action constructor.

You could achieve the same effect like this:

label1.Invoke(SetText);
...
public void SetText() { label1.Text = Line; }

or like this:

label1.Invoke(new Action(SetText));
...
public void SetText() { label1.Text = Line; }

or like this:

label1.Invoke(new Action(delegate() { label1.Text = Line; }));

or like this:

label1.Invoke(delegate() { label1.Text = Line; });

or like this:

label1.Invoke(() => label1.Text = Line);

These are mostly just syntactic shortcuts to make it easier to represent an action.

Note that lambda expressions often have parameters. When there is only one parameter, the parentheses are optional:

list.ToDictionary(i => i.Key);

When there are no parameters or multiple parameters, the parentheses are necessary to make it obvious what you're doing. Hence, the () =>.

Solution 2

Let's break it down piece by piece.

label1.Invoke(

This is the Control.Invoke method. Here's how it's defined:

public Object Invoke(Delegate method);

Executes the specified delegate on the thread that owns the control's underlying window handle.

What that means is that you give it a reference to a method to call, and Control.Invoke will make sure it gets called on the UI thread (which will prevent cross-threading exceptions while updating the UI.) It takes a default Delegate as a parameter, which means you need to pass it a method that takes no parameters and has no return value. That's where the System.Action delegate type comes in:

public delegate void Action();

Using lambda expressions, we can create an Action delegate inline. First, we specify the delegate type:

label1.Invoke(new Action(

Then, we will begin the lambda syntax. An empty set of parenthesis will denote that the lambda function takes no parameters, and an "arrow" afterwards shows that we want to start the method:

label1.Invoke(new Action(() =>

Now, because the lambda method has no return value (but must execute a statement) we need to surround the code we want to execute on the UI thread in curly braces:

label1.Invoke(new Action(() =>
{
    label1.Text = Line;
}

Close up the remaining parenthesis, and you have the full, finished statement.

label1.Invoke(new Action(() =>
{
    label1.Text = Line;
}));

Solution 3

Generally when you want to add something to you GUI and you are working from another thread you need to do something called Invocation.

To make an invocation you use either a Controls Invoke method or the something like an Application Dispatcher, these methods generally take an Action. An Action is just what it sounds like, something that is to be performed.

In your case what you are doing is that you want to add a line of text to an element that lives on your GUI, so what you need to do is to create an Action ( anonymouse method ) and in this action you just say "Add this to my Control". And then you Invoke this to avoid cross-threading problems.

()=> is just a "shortcut"(lambda way) to create a method, that is anonymous. This means that you can't call this from anywhere but the context of where you created the anonymous method.

You can also Invoke a "global" method, it doesn't have to be an anonymous method.

Solution 4

An Action is a delegate type, in other words it encapsulates a function. Specifically an Action encapsulates a function that returns void, whereas for instance a Func would encapsulate a function with a return value. These are alot like a function pointers in C++ -- essentially a reference to a function ie a way to encapsulate behavior.

The .Invoke() method takes the Action delegate and runs the function it points to. In this case the function it points to is the lambda expression:

() => { label1.Text = Line }

The initial parentheses denote any parameters being passed into the function. In this case there are no parameters so the parentheses are empty. For example if you wanted to pass in two strings, you would do:

var action = new Action<string, string>( (x, y) => { // use x and y }

Whatever follows the '=>' expression is essentially the body of the function. You have access to the variables specified in the parentheses inside the scope of this body.

Altogether this is a quick way to create an anonymous function on the fly that essentially is equivalent to the following:

public void SetLine()
{
   label1.Text = Line; 
}

As such you could also create that Action object by doing:

var action = new Action(SetLine) 

where you are passing in the name of the method to encapsulate instead of passing in a lambda. Whats passed in is known as a 'Method Group'.

Solution 5

Action is a delegate. Label1.Invoke() is being used to execute the code label1.Text = line to avoid Cross Threading Operation. the event handler for DataReceived event is executing on a different thread other than UI thread. label1.Invoke() will execute the code in UI thread.

Share:
19,020

Related videos on Youtube

Richard
Author by

Richard

Updated on June 04, 2022

Comments

  • Richard
    Richard over 1 year

    I am new to c# and do not understand the syntax of invoking a new action or even what an action is. From my understanding in Port1_DataReceived, I have to create an action because I am in a new tread... Can anyone elaborate on why I need to do this?

    public Form1()
    {
        InitializeComponent();
        SerialPort Port1 = new SerialPort("COM11", 57600, Parity.None, 8, StopBits.One);
        Port1.DataReceived += new SerialDataReceivedEventHandler(Port1_DataReceived);
        Port1.Open();
    }
    
    
    private void Port1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
         SerialPort Port = (SerialPort)sender;
         string Line = "";
         int BytestoRead = Port.BytesToRead;
         Line = Port.ReadLine();
         label1.Invoke(new Action(() =>
         {
              label1.Text = Line;
          }));
    }
    

    The code snip that I am really having trouble understanding is:

    label1.Invoke(new Action(() =>
             {
                  label1.Text = Line;
              }));
    

    Can someone break down what this is doing.. I am sure it is nothing to complicated, just that I have never seen anything like it before. The syntax that is really holding me up is ()=> the new action is pointing to the code below or something??

  • toughQuestions
    toughQuestions over 3 years
    So, when doing "label1.Invoke(() => label1.Text = Line);" or even "label1.Invoke(new Action(() => label1.Text = Line));", why using Invoke and Action at all? Why no simply do: "label1.Text = Line;"? Thanks
  • toughQuestions
    toughQuestions over 3 years
    Great explanation, I know the thread is old, but why using Action at all in this case and not only do "label1.Text = Line;"
  • StriplingWarrior
    StriplingWarrior over 3 years
    @toughQuestions: The handler where this code lives is going to execute on a background thread. Messing with the properties on Controls will throw an exception if you're not on the UI thread. The Invoke method makes sure the code in the Action is executed on the UI thread. See the docs for Control.Invoke().