What's the method signature for passing an async delegate? - c#

I've recently moved back to C# from being in Objective-C land, and the async/await keywords in C# 5 look cool. But I'm still trying to get a handle on the proper syntax.
I want to declare a method that takes an asynchronous delegate as a parameter, but I am having trouble getting both the caller and the callee syntax correct. Can someone provide a code sample showing the method declaration, the call, and a call to the delegate?
I'm thinking the declaration would be something like the following. Note that this function isn't asynchronous; i.e. its asynchronicity is independent of the delegate.
void DoSomethingWithCallback(async delegate foo(int))
{
...
foo(42);
...
}
The call would be something like:
DoSomethingWithCallback(async (int x) => { this.SomeProperty = await SomeAsync(x); });
Of course none of this compiles and most of the samples I've seen assume that one has a field or property that's the delegate, rather than the anonymous delegate I'd like to use.

A function that takes a delegate as a parameter must use a named delegate type; unlike in Objective-C you can't declare an anonymous delegate type inline in the function definition. However, the generics Action<> and Func<> are provided so that you don't have to declare a new type yourself. In the code below I'm assuming the delegate takes a single int as a parameter.
void DoSomethingWithCallback(Func<int,Task> callbackDelegate)
{
Task t = callbackDelegate(42);
}
If this function doesn't actually do anything with the Task object returned (as with the code shown above), you can instead use Action<int> as the delegate type. If you use Action, you can still declare the delegate async (below) but the implicit Task object returned is ignored.
The lambda syntax for calling the above function is straightforward and the syntax you used in the question is correct. Note that the parameter type doesn't need to be specified here since it can be inferred:
DoSomethingWithCallback(async (intParam) => { this.myint = await Int2IntAsync(intParam); });
You can also pass a method or delegate variable, if you wish, instead of using the lambda syntax:
async Task MyInt2Int(int p) { ... }
Func<int,Task> myDelegate;
void OtherMethod()
{
myDelegate = MyInt2Int;
DoSomethingWithCallback(myDelegate); // this ...
DoSomethingWithCallback(MyInt2Int); // ... or this.
}

If I have a task that I want to be passed but not executed, I can wrap the Task in a Func<>, then call that Func<> to create that task. The await can be used in the normal way.
public class Example {
public Example(Func<Task> toBeExecutedInTheFuture)
{
FutureTask = toBeExecutedInTheFuture;
}
public async void ExecuteTaskExample()
{
await FutureTask();
// or alternatively
var myTask = FutureTask();
// do work
await myTask;
}
}

The return type of the method signatue is Task if there is no return type, or Task<T> if there is a return type.
Tho, I'm not 100% certain if you can have async lambdas like that.
In the method that is consuming the task, you would either 'await' the task or use the properties and methods on Task to get the result.

Please take a look to this example, with Task and an additional parameter.
I hope this can help people understanding how to implement it...
// ... more code ...
// Let's call a function with a Task<T> parameter (LocalFunc)
await CustomFunctionAsync(
param1,
LocalFunc
);
// ... more code ...
Declared functions:
public static async Task CustomFunctionAsync(int param1, Func<string, Task<string>> processingFunc = null)
{
string result = null;
if (processingFunc != null)
result = await processingFunc("https://www.google.com/");
}
public async Task<string> LocalFunc(string url)
{
// processing...
}

Related

How can I call an async method inside an anonymous delegate?

I have a function takes a delegate as input parameter.
public delegate bool Callback();
public static class MyAPI
{
public static handle(Callback callback) {
...
}
}
So I call the api with an anonymous delegate like this
MyAPI.handle(delegate
{
// my implementation
});
My question is how can i call an async method in my anonymous delegate?
MyAPI.handle(delegate
{
// my implementation
await MyMethodAsync(...);
});
I get an error saying the 'await' operator can only be used within async anonymous method'?
The function MyAPI.handle() only expect a non async delegate. I can't change that method. How can I fix my problem?
Thank you.
You could call an asynchronous method by passing an async lambda expression:
MyAPI.handle(async () =>
{
// my implementation
await MyMethodAsync(...);
});
MyAPI.handle(async () =>
{
// my implementation
await MyMethodAsync(...);
});
Another solution for people like me that don't really like how lambdas look.
MyAPI.handle(
async delegate() {
// my implementation
await MyMethodAsync(...);
}
);

How does the keyword delegate work compared to creating a delegate

I'm slowly getting my head around delegates, in that the signature of the delegate must match that of the method it is delegating too.
However, please review the following code.
public static void Save()
{
ThreadStart threadStart = delegate
{
SaveToDatabase();
};
new Thread(threadStart).Start();
}
private static void SaveToDatabase() { }
I am now stumped at this point, because the delegate returns void (as that is what SaveToDatabase() is) but, it's clearly returning a ThreadStart... Or is it?
If I were to write my own delegate, I would have no idea how to achieve this because the delegate would have to be void to match the return type of SaveToDatabase(). But it can't be; it would be of type ThreadStart!
My question is, have I totally mis-understood or is this made possible by some .NET trickery? If I wanted to write this method but create my own delegate, how would I ?
The word "delegate" is a bit abused. It's easier with classes and objects. A "class" is like a blueprint for an object. An "object" is an actual instance in memory, which follows the blueprint of the class.
For delegates we use the same word, hence I suspect your confusion. Consider the following code:
class Main
{
public delegate int DelegateType(string x);
public int SomeFunction(string y) { return int.Parse(y)*2; }
public void Main()
{
DelegateType delegateInstance = null;
delegateInstance = SomeFunction;
int z = delegateInstance("21");
Console.WriteLine(z);
}
}
This code outputs "42".
The DelegateType is the type of the delegate. Like a class is a blueprint for an object, the delegate is a blueprint for a function.
So later we create a variable named delegateInstance which is of the type DelegateType. To that variable, we can assign ANY function that takes a single string parameter and returns an integer. Note, that we assigned the function itself, not the results of that function. It's like the delegateInstance variable is now a synonym of that function. Indeed, as demonstrated a line later, we can now use delegateInstance to call that funcion! Just as if delegateInstance was a function itself. But, since it is variable, we can also do all the same things that we usually do with variables - like pass them as parameters to other functions, or even return from other functions (A function that returns a function! Wrap your head around that!)
OK, let's see the code that baffled you.
public static void Save()
{
ThreadStart threadStart = delegate
{
SaveToDatabase();
};
new Thread(threadStart).Start();
}
private static void SaveToDatabase() { }
First thing to notice is that you used an anonymous delegate. Another misuse of the term. When compiled, it results in something like this:
public static void Save()
{
ThreadStart threadStart;
threadStart = __ASDASDASD6546549871;
var tmp = new Thread(threadStart);
tmp.Start();
}
private static void SaveToDatabase() { }
private void __ASDASDASD6546549871()
{
SaveToDatabase();
}
Note that your anonymous function was actually transformed to a completely regular function with a random name, and then that function was assigned to the threadStart variable.
So now this is just like the example above. Just replace DelegateType with ThreadStart, delegateInstance with threadStart and SomeFunction with __ASDASDASD6546549871.
Does it make sense now?
I am now stumped at this point, because the delegate returns void (as that is what SaveToDatabase() is) but, it's clearly returning a ThreadStart... Or is it?
If I were to right my own delegate, I would have no idea how to achieve this because the delegate would have to be void to match the return type of SaveToDatabase(), but can't be because it would be of type ThreadStart!
ThreadStart is defined as a delegate. In fact, it is defined as
public delegate void ThreadStart();
So your code is not returning a delegate or a ThreadStart. It is simply defining a function that matches the ThreadStart delegate definition. The Thread constructor expects a ThreadStart delegate, which you have defined as the variable threadStart, which points to the SaveToDatabase function.
I tend to think of delegates as the old C++ term "function pointers". Delegates allow us to specify what kind of function (parameters and return type) should be passed as a parameter to another function.
My question is, have I totally mis-understood or is this made possible by some .NET trickery? If I wanted to write this method but create my own delegate, how would I ?
I think you may have misunderstood. But to answer this question specifically, the method you would write would just need to match the definition specified by the delegate type, in this case ThreadStart. That method definition must return void and accept no parameters. Your SaveToDatabase method matches this delegate type and is therefore the proper delegate method to create.
When you are going to run an administrated subProcess, the method that is going to be executed gets represented by ThreadStart or ParameterizedThreadStart, but SaveToDatabase is void and it will be executed with void signature, not with ThreadStart type.
Example from MSDN:
class Test
{
static void Main()
{
// To start a thread using a static thread procedure, use the
// class name and method name when you create the ThreadStart
// delegate. Beginning in version 2.0 of the .NET Framework,
// it is not necessary to create a delegate explicityly.
// Specify the name of the method in the Thread constructor,
// and the compiler selects the correct delegate. For example:
//
// Thread newThread = new Thread(Work.DoWork);
//
ThreadStart threadDelegate = new ThreadStart(Work.DoWork);
Thread newThread = new Thread(threadDelegate);
newThread.Start();
// To start a thread using an instance method for the thread
// procedure, use the instance variable and method name when
// you create the ThreadStart delegate. Beginning in version
// 2.0 of the .NET Framework, the explicit delegate is not
// required.
//
Work w = new Work();
w.Data = 42;
threadDelegate = new ThreadStart(w.DoMoreWork);
newThread = new Thread(threadDelegate);
newThread.Start();
}
}
class Work
{
public static void DoWork()
{
Console.WriteLine("Static thread procedure.");
}
public int Data;
public void DoMoreWork()
{
Console.WriteLine("Instance thread procedure. Data={0}", Data);
}
}
From MSDN
A delegate is a type that references a method. Once a delegate is assigned a method, it behaves exactly like that method. The delegate method can be used like any other method, with parameters and a return value, as in this example:
public delegate int PerformCalculation(int x, int y);
So return type of the delegate will match the return type of the method it is delegating.
Any method that matches the delegate's signature, which consists of the return type and parameters, can be assigned to the delegate. This makes is possible to programmatically change method calls, and also plug new code into existing classes. As long as you know the delegate's signature, you can assign your own delegated method.

how to use Asynchronous delegates on a void return method

i want to make a method async
public static void PrepareData<T>()
{
// prepare data ....
}
i was trying to do the following
Func method = PrepareData<T>;
method.invoke
...
but it complain Func must specify something e,g Func
so my question is, how to make a void return method asyn??
Thanks.
You should use Action instead of Func. The Action family is for functions with a void return type, Func is for those that actually return something.
You have to use the Action<T> instead

What is the purpose of delegates in .NET

So I'm a little bit confused about delegates in C#.... what do they do and how are they useful? I've read a few tutorials, and I don't really get exactly what they're supposed to do (everyone relates them to function pointers in C, and I've never programmed in C).
So... what do delegates do? What's a scenario in which I should use them? How would I then use them?
The other answers are good, but here's another way to think about delegates that might help. Imagine that a delegate is nothing more than an interface. When you see:
delegate void Action();
think:
interface IAction
{
void Invoke();
}
And when you see:
Action myAction = foo.Bar;
think:
class FooBarAction : IAction
{
public Foo Receiver { get; private set; }
public FooBarAction(Foo foo)
{
this.Receiver = foo;
}
public void Invoke()
{
this.Receiver.Bar();
}
}
...
IAction myAction = new FooBarAction(foo);
And when you see
myAction();
think
myAction.Invoke();
The actual details of what types get constructed are a bit different, but fundamentally that's what's happening. A delegate is simply an object with a method called Invoke, and when you call that method, it calls some other method on some other object on your behalf. That's why it's called a "delegate" -- because it delegates the call to another method of another object.
Delegates are sort of like objects that represent a method call. One useful way they can be used are as callbacks. For example, imagine you have a method that does something asynchronous, and you want the caller to be able to specify what they want to happen once it completes (Action is a type of delegate):
public void DoSomething(Action whatToDoWhenDone)
{
// Your code
// See how the delegate is called like a method
whatToDoWhenDone();
}
A user of DoSomething can now specify the callback as a parameter:
public void AnotherMethod()
{
DoSomething(ShowSuccess); // ShowSuccess will be called when done
}
public void ShowSuccess()
{
Console.WriteLine("Success!");
}
You can also use lamba expressions as a shorter way of writing your delegate:
public void AnotherMethod()
{
DoSomething(() => Console.WriteLine("Success!"));
// Also DoSomething(delegate() { Console.WriteLine("Success!"); });
}
Callbacks are far from the only use cases for delegates. Hopefully this shows you some of their power: the ability to have code to be executed as a variable.
Delegates allow you to treat functions as if they were any other variable. A delegate type defines the signature of the function, that is, what the function returns, and the number and type of arguments that it takes:
// This is the delegate for a function that takes a string and returns a string.
// It can also be written using the framework-provided Generic delegate Func, as
// Func<String, String>
delegate String StringToStringDelegate(String input);
You can define a variable of this type, and assign it to an existing method. I use the generic as an example, because that is the more common usage in .net since 2.0:
String Reverse(String input) {
return input.Reverse();
}
Func<String, String> someStringMethod = new Func<String, String>(Reverse);
// Prints "cba":
Console.WriteLine(someStringMethod("abc"));
You can also pass functions around this way:
String Reverse(String input) {
return input.Reverse();
}
String UpperCase(String input) {
return input.ToUpper();
}
String DoSomethingToABC(Func<String, String> inputFunction) {
return inputFunction("abc");
}
var someStringMethod = new Func<String, String>(Reverse);
// Prints "cba":
Console.WriteLine(DoSomethingToABC(someStringMethod));
var someOtherStringMethod = new Func<String, String>(UpperCase);
// Prints "ABC":
Console.WriteLine(DoSomethingToABC(someOtherStringMethod));
In a big application it is often required to other parts of the application based on some condition or something else. The delegate specifies the address of the method to be called. In simple manner a normal event handler implements the delegates in the inner layers.
The oversimplified answer is that a delegate is basically a "pointer" to a block of code, and the benefit is that you can pass this block of code into other functions by assigning your block of code to a variable.
The reason people relate Delegates to C function pointers is because this is in essence what delegation is all about, I.e.: Pointers to methods.
As an example:
public void DoSomething(Action yourCodeBlock)
{
yourCodeBlock();
}
public void CallingMethod()
{
this.DoSomething(
{
... statements
});
this.DoSomething(
{
... other statements
});
}
There are naturally lots of ways to invoke delegates as all of the tutorials will show you. The point is though that it allows you to "delegate" functionality in such a way that you can call into methods without necessarily knowing how they work, but simply trusting that they will be taken care of. In other words, I might create a class that implements a "DoSomething()" function, but I can leave it up to someone else to decide what DoSomething() will do later on.
I hope that helps. :-)
Delegates are a way to call back into your code when a long running operation completes or when an event occurs. For example, you pass a delegate to a method that asynchronously downloads a file in the background. When the download is complete, your delegate method would be invoked and it could then take some action such as processing the file's contents.
An event handler is a special type of delegate. For example, an event handler delegate can respond to an event like a mouse click or key press. Events are by far the most common type of delegate. In fact, you will typically see the event keyword used far more often in C# code than the delegate keyword.
You can think of it as a type in which you may store references to functions. That way you can in effect, store a function in a variable so you may call it later like any other function.
e.g.,
public delegate void AnEmptyVoidFunction();
This creates a delegate type called AnEmptyVoidFunction and it may be used to store references to functions that return void and has no arguments.
You could then store a reference to a function with that signature.
public static void SomeMethod() { }
public static int ADifferentMethod(int someArg) { return someArg; }
AnEmptyVoidFunction func1 = new AnEmptyVoidFunction(SomeMethod);
// or leave out the constructor call to let the compiler figure it out
AnEmptyVoidFunction func2 = SomeMethod;
// note that the above only works if it is a function defined
// within a class, it doesn't work with other delegates
//AnEmptyVoidFunction func3 = new AnEmptyVoidFunction(ADifferentMethod);
// error wrong function type
Not only can it store declared functions but also anonymous functions (i.e., lambdas or anonymous delegates)
// storing a lambda function (C#3 and up)
AnEmptyVoidFunction func4 = () => { };
// storing an anonymous delegate (C#2)
AnEmptyVoidFunction func5 = delegate() { };
To call these delegates, you can just invoke them like any other function call. Though since it is a variable, you may want to check if it is null beforehand.
AnEmptyVoidFunction func1 = () =>
{
Console.WriteLine("Hello World");
};
func1(); // "Hello World"
AnEmptyVoidFunction func2 = null;
func2(); // NullReferenceException
public static void CallIt(AnEmptyDelegate func)
{
// check first if it is not null
if (func != null)
{
func();
}
}
You would use them any time you needed to pass around a method that you wish to invoke. Almost in the same way that you may pass instances of objects so you may do what you wish with them. The typical use case for delegates is when declaring events. I have written another answer describing the pattern so you can look at that for more information on how to write those.

Argument type 'void' is not assignable to parameter type 'System.Action'

This is my test code:
class PassingInActionStatement
{
static void Main(string[] args)
{
var dsufac = new DoSomethingUsefulForAChange();
dsufac.Do(WriteToConsole);
dsufac.Do2(s => WriteToConsoleWithSomethingExtra("Test"));
dsufac.Do(WriteToConsoleWithSomethingExtra("Test")); // Does not compile
}
internal static void WriteToConsole()
{
Console.WriteLine("Done");
}
internal static void WriteToConsoleWithSomethingExtra(String input)
{
Console.WriteLine(input);
}
}
internal class DoSomethingUsefulForAChange
{
internal void Do(Action action)
{
action();
}
internal void Do2(Action<String> action)
{
action("");
}
}
The first 2 calls work but I am wondering why the 3rd one does not. I do not fancy the code inside Do2 as it seems strange that I have type type action("") in there in order to get it to work.
Could someone please explain the 2 things I do not understand please?
Why I can not write the third line like that with calling Do
Why I have to write action("") in order get it to work in Do2
dsufac.Do(WriteToConsoleWithSomethingExtra("Test"));
actually calls the function first (WriteToConsoleWithSomethingExtra("Test")) and then attempts to pass the result into Do. Since there is no result (void), it's not possible.
What you actually want is this:
dsufac.Do(() => WriteToConsoleWithSomethingExtra("Test"));
The inner part declares a function that takes nothing (the () => bit), which calls WriteToConsoleWithSomethingExtra("Test") when executed. Then your dsufac.Do call will receive an action, like it expects.
As for Do2 - you've declared it as taking Action<String>, which means that action is a function that takes one argument. You have to pass it a string. That string might be empty, like in your action("") example, or it might be passed in externally, as in something like this:
dsufac.Do3(WriteToConsole, "Test");
...
internal void Do3(Action<String> action, String str)
{
action(str);
}
In your code
dsufac.Do(WriteToConsoleWithSomethingExtra("Test"));
is interpreted like the following
var variable = WriteToConsoleWithSomethingExtra("Test");
dsufac.Do(variable);
As the return type of WriteToConsoleWithSomethingExtra("Test") is void, so you can not actually pass it to dsufac.Do(). That is why its not getting compiled. But for the first one
dsufac.Do(WriteToConsole);
you are not calling the function, rather you are passing it as a method group, which is later get invoked in the Do() method of dsufac object. But if you want to write the 3rd line as the 1st one, you can use
dsufac.Do(() => WriteToConsoleWithSomethingExtra("Test"));
Do expects an Action (i.e. method which take no parameters and returns no value). Hence WriteToConsoleWithSomethingExtra is not a valid fit - takes one string parameter.
Do2 accepts an Action<T> (i.e. method which takes in one T parameter and returns no value). Hence when you invoke the delegate/action you need to supply one parameter of type T, here String.

Categories

Resources