Conceptually what does an Action<Action<T>> represent - c#

I understand that an Action represents an action to be performed on an object, however in a few code bases I have seen parameters declared as Action<Action<T>> and struggle to understand what an action to be performed on another action means.
So conceptually what does an Action<Action<T>> represent, and can you suggest an example where you would use one ?

Starting from the end, I have used this pattern to create a multithreaded "progress" dialog while long tasks run on the main thread. I call my progress dialog creating function with a lambda that does the work, which receives a lambda that knows how to update the progress bar and status text. Something like this:
LongRunningOperation.Run((update)=>
{
update("phase 1");
// do work for phase 1
update("phase 2");
// do work for phase 2
});
So my Run function is declared like this:
public static void Run(Action<Action<string>> worker);
Generalizing, any worker lambda that receives a lambda from the function itself would use this pattern.

An Action<Action<T>> is a delegate which takes an Action<T> as its argument. This would allow you to pass around a delegate, which, when called, would get passed a second delegate (of type Action<T>).
Usages of this would (or should) be quite rare, however. Typically, you can just use a single Action<T> and pass that around. The only place I could see this being used would be a scenario such as a storing a set of delegates inside of a collection.
For example, suppose you had a series of operations that worked on a Person class. This could be defined as: List<Action<Person>> actions; Given this, if you wanted to use List<T>.ForEach to execute all of these methods upon some specific person, provided some criteria fit, you could do something like:
Person person = GetPersion();
actions.ForEach( action =>
{
if (person.Foo)
action(person); // Call the action on the person
});
The above lambda would be an Action<Action<Person>>. (I would personally not write code like this, however, and would instead recommend a normal foreach loop - this was just for illustration purposes to demonstrate how this could arise...)

Instead of thinking of it as an action to be performed on another action, think of it as an action that takes another action as a parameter. For example, you may have an action thats job is to enqueue another action for executing at a later time:
class WorkProcessor
{
public Action<Action<WorkItem>> WorkScheduler { get; set; }
public void ScheduleWork(WorkItem workItem)
{
WorkScheduler(ProcessWork);
}
public void ProcessWork(workItem)
{
//...
}
}

An Action<Action<T>> is a (delegate to a) function that takes another (delegate to a) function as its argument. Such a "higher order function" can then invoke its argument multiple times, conditionally, with logging, etc. Such a function allows you to encapsulate program logic and pass it around.
Here's a simple example, in which the choice of whether or not to log function calls is made in Main(), and the implementation of that choice is then invisible to to the actual worker function; instead of passing the configuration flag around, you pass a higher order function that encapsulates the choice.
void Run( Action<int> fn, int x )
{
fn(x);
}
void RunAndLog( Action<int> fn, int x )
{
print( "before " + x );
fn(x);
print( "after " + x );
}
void InvokeWorkerTenTimes( Action<Action<int>> gn, Action<int> fn )
{
// fn is WHAT to do
// gn is HOW to do it!
for( int i=0; i<10; i++ )
gn(fn, i);
}
void DoWork(int x)
{
}
void Main()
{
if( LoggingEnabled )
InvokeWorkerTenTimes( RunAndLog, DoWork );
else
InvokeWorkerTenTimes( Run, DoWork );
}

Related

Passing Actions into generic functions

I'm trying to wrap my head around different concepts in Csharp by trying different things. A create a generic function that takes in an action. The action has one input parameter and returns void. I create a simple action that is linked to a lambda function (returns void has one parameter x). I am able to run the action but when I pass the function to my generic function I am not sure how to add the input parameter. act("Some Int") doesn't work.
How do I pass in a value to an action?
public MainWindow()
{
InitializeComponent();
Action<int> myAction = (x) => Console.WriteLine(x);
myAction(13);
test(myAction);
}
private static void test<T>(Action<T> act)
{
act(); // How do i pass in an int Here?
}
Simply calling act("Some Int") as you have just required the Action act to be a genric function. Therefore you cannot specifically invoke it with one fixed variable type. You can solve your problem by modifying the test-method
private static void test<T>(Action<T> act, T value)
{
act(value); // How do i pass in an int Here?
}
...
test(myAction,integerValue);
Now you can call the Action with a given intvalue.
I can see what you are trying to do, and just wanted to throw this pattern up, since we often do this when we have to use closures and the parameters could be wildly different.
In those cases, rather than define an Action<T> which kind of ties you down from being able to use closures, you would just simply define your method as Action. So test would look like this:
private static void test(Action act)
{
act(); // yup, that's all there is to it!
}
So how would you pass in the parameter(s)? Simple: use closures. Like this:
public MainWindow()
{
InitializeComponent();
var x = 13; // this defined outside now...
Action myAction = () => Console.WriteLine(x); // you're basically using the closure here.
myAction();
test(myAction);
}
We often use this sort of approach when we're context switching (aka thread jumping), and need the thread continuation to pick up one or more variable values at the point it executes. That's just one example, there's quite a few other valid use cases as well.
Your experimental example, if I'm reading it correctly, could also qualify as a situation where closures could be a good fit.

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

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.
I think you're overthinking things a little bit. So let's start from the top:
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;
});
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
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)().
Can't you use DynamicInvoke() on that delegate (it takes params object[] args as argument)
action.DynamicInvoke(arg1, arg2, arg3 );

Passing statement lambda as parameter

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

Can a method be attached to a delegate with predefined parameters?

Sometimes I encounter cases where I have to attach a method to a delegate but the signature doesn't match, like trying to attach abc down there to somedelegate with the string parameter being "hi".
public class test
{
//...
public void abc(int i, string x)
{
//Do Something
}
//...
}
public class test2
{
somedelegate x;
//...
public test2()
{
//Do Something
test y = new test();
x += y.abc(,"hi");
}
delegate void somedelegate(int i);
}
I can work it around by creating another delegate with the correct signature then attaching it but it seems so unnecessarily complex. Can you do something like this in C#? Thanks.
EDIT: I guess there closest to what I wanted to achieve is:
x += (int i) => abc(i, "hi");
Yes, you can do this with closures
[there's a nice treatment of the subject on msdn, but like anything else in there it's hard to find]
The Big Picture
Write a method that can take all the parameters you need
Inside that method you return an anonymous method with the delegate-target signature it requires
This method's call is itself the parameter in the delegate instantiation
Yes, this is a bit Matrix-y. But way cool.
delegate void somedelegate (int i);
protected somedelegate DelegateSignatureAdapter ( string b, bool yesOrNo, ...) {
// the parameters are local to this method, so we'll go w/ that.
// our target delegate requires a single int parameter and void return
return (int a) => {
// your custom code here
// all calling arguements are in scope - use them as needed
}; // don't forget the semicolon!
}
// our delegate call
somedelegate myWarpedDelegate = new somedelegate (DelegateSignatureAdapter("someString", true));
myWarpedDelegate (2543);
myWarpedDelegate(15);
Just Googling for '.net delegate optional parameters' returns some results that may be useful:
Can a Delegate have an optional parameter?
VB.NET - Is there a way to utilize optional parameters in delegates? (Or Plans to Allow this?)
Optional Parameters and Delegates
Update (researching this some more, and helped by the first link above):
Could you perhaps use the Invoke method, which accepts any delegate?

Help with understanding C# syntax while Invoking a new Action

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??
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 () =>.
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;
}));
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.
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'.
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.
This is generating an anonymous method (a lambda, precisely) and passing that to the invoke method. Lambdas are a great way to have code you only need once so you don't need a lot of helper methods doing one thing only.
This is ensuring that the label's text is running in the UI thread. The Port1_DataReceived event will likely run in a background thread, and the Label's text value should not be set from background threads. This prevents that from happening.
I don't know what the label1 is, but the could could be read as:
label1 is an Action, that recieves another action as parameter. It does something and when it calls action recieved in argument.
Now, I've read that and I could be a problem - label1 could not be an Action. As it is just a control which set here: label1.Text = Line;
You have an error in your app;
EDIT
Sorry, just read that:
http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx
Executes the specified delegate on the thread that owns the control's underlying window handle.
Code is correct.

Categories