Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use .NET Action to execute a method with unknown number of parameters?

Tags:

I want to execute some operations on a worker thread while displaying a progress bar to the user. I've created a class

public class ProgressBar {    public void StartAsyncTask(Action action)    {       Task t = new Task(action);       t.start();    } } 

I found out that I can send any method to the StartAsyncTask in the following way:

  ProgressBar pb = new ProgressBar();   pb.StartAsyncTask( () => DoSomething(15, "something"));    public void DoSomething(int i, string s)    {       //do something    } 

First of all, I can't seem to understand what is and how is lambda expression - () => - translated and how is the Action object passed a delegate with an unknown number of parameters.

I would like to use a BackgroundWorker with my ProgressBar but in this case I would need to invoke the action. So something like this:

void m_backgroundWorker_DoWork(object sender, DoWorkEventArgs e) {     Action action = e.Argument as Action; //same action here passed through EventArgs    //but already in a worker thread so no need for the Task object      //and now i need to somehow invoke the action object but i don't know what the parameters are.      action.Invoke( ? );  } 

How is it possible in the first example to execute the action without knowing the parameters in StartAsyncTask(Action action) method?

Why do I need to know the parameters when invoking the action in this case?

Everything about how/why/when to use "Action" is pretty unclear to me even if I read MSDN documentation and some other threads here. Any information on this will help me.

like image 894
Dan Dinu Avatar asked Nov 06 '12 22:11

Dan Dinu


People also ask

What can you use to pass parameters to actions?

You can pass them via a URL, a query string, a request header, a request body, or even a form.

How do you pass an action to a method in C#?

Use Action Delegate to Pass a Method as a Parameter in C# We can also use the built-in delegate Action to pass a method as a parameter. The correct syntax to use this delegate is as follows. Copy public delegate void Action<in T>(T obj); The built-in delegate Action can have 16 parameters as input.

How do you call a method with parameters in another method in C#?

You can use the Action delegate type. Then you can use it like this: void MyAction() { } ErrorDBConcurrency(e, MyAction); If you do need parameters you can use a lambda expression.

What are the different ways to pass parameters in C#?

In C#, arguments can be passed to parameters either by value or by reference. Passing by reference enables function members, methods, properties, indexers, operators, and constructors to change the value of the parameters and have that change persist in the calling environment.


1 Answers

I think you're overthinking things a little bit. So let's start from the top:

  1. A lambda expression is a notation to reference a method execution. Example:

     x => x + 3 

    At the most basic level, this is representing a function that takes 1 input, x, and then returns a value equal to x + 3. So in your situation, your expression:

    () => DoSomething(15, "Something") 

    Represents a method taking 0 parameters, and then invoking the method DoSomething(15, "Something"). The compiler is behind the scenes translating that into a Func or Action delegate for you. So it is in effect:

    new Action(delegate() {     DoSomething(15, "Something") });  

    The compiler rewrite of my simple expression above would be:

    new Func<int, int>(delegate(int x) {     return x + 3; }); 
  2. Next up, if you want to invoke an action later, the syntax for doing so is fairly straightforward:

    Action someMethod = new Action(() => { Console.WriteLine("hello world"); })); someMethod(); // Invokes the delegate 

    So if you have a given Action instance, simply invoking it with the () syntax is all you need, since Action is a delegate that takes 0 parameters and returns nothing.

    A function is similarly easy:

    Func<int, int> previousGuy = x => x + 3; var result = previousGuy(3); // result is 6 
  3. Lastly, if you want to pass along a method to invoke, and you don't have context for the parameters at that point, you can simply wrap your call in an action and invoke that later. For example:

    var myAction = new Action(() =>      {           // Some Complex Logic           DoSomething(15, "Something");           // More Complex Logic, etc      });  InvokeLater(myAction);  public void InvokeLater(Action action) {       action(); } 

    All of the data is captured in a closure of your method, and thus is saved. So if you can manage to pass along an Action to your event with the e.Argument property, all you would need to do would be to call (e.Argument as Action)().

like image 85
Tejs Avatar answered Oct 06 '22 02:10

Tejs