Check if Action is async lambda - c#

Since I can define an Action as
Action a = async () => { };
Can I somehow determine (at run time) whether the action a is async or not?

No - at least not sensibly. async is just a source code annotation to tell the C# compiler that you really want an asynchronous function/anonymous function.
You could fetch the MethodInfo for the delegate and check whether it has an appropriate attribute applied to it. I personally wouldn't though - the need to know is a design smell. In particular, consider what would happen if you refactored most of the code out of the lambda expression into another method, then used:
Action a = () => CallMethodAsync();
At that point you don't have an async lambda, but the semantics would be the same. Why would you want any code using the delegate to behave differently?
EDIT: This code appears to work, but I would strongly recommend against it:
using System;
using System.Runtime.CompilerServices;
class Test
{
static void Main()
{
Console.WriteLine(IsThisAsync(() => {})); // False
Console.WriteLine(IsThisAsync(async () => {})); // True
}
static bool IsThisAsync(Action action)
{
return action.Method.IsDefined(typeof(AsyncStateMachineAttribute),
false);
}
}

Of course, You can do that.
private static bool IsAsyncAppliedToDelegate(Delegate d)
{
return d.Method.GetCustomAttribute(typeof(AsyncStateMachineAttribute)) != null;
}

If you're looking to build some logic, based on whether a sync or async lanbda has been passed to your method - just introduce overloads.
public void MyMethod(Action action)
{
DoStuff();
}
public void MyMethod(Func<Task> asyncAction)
{
DoOtherStuff();
}

Related

Passing argument to an Action without using an anonymous function?

Is there a way I can pass through an argument to an Action without using an anonymous function?
Eg, the following code works fine:
private void doSomethingAndLogIt(string log, Action dosomething)
{
Debug.WriteLine(log);
dosomething();
}
private void multiplyIt()
{
_result = "great";
}
...
doSomethingAndLogIt("Did something", multiplyIt);
but what I want to do is this:
private void doSomethingAndLogIt(string log, Action<int> dosomething)
{
Debug.WriteLine(log);
dosomething(???);
}
private void multiplyIt(int a)
{
_result = "great";
}
doSomethingAndLogIt("Did something", multiplyIt(5));
I realise that I can do this:
private void doSomethingAndLogIt(string log, Action<int> dosomething, int inputValue)
{
Debug.WriteLine(log);
dosomething(inputValue);
}
private void multiplyIt(int a)
{
_result = "great";
}
doSomethingAndLogIt("Did something", multiplyIt, 5);
but it's pretty confusing. I also realise that I can do this:
doSomethingAndLogIt("Did something", () => {
multiplyIt(5);
});
but it would be great if I could do this:
doSomethingAndLogIt("Did something", multiplyIt(5));
You do not need to do anything special. This code below:
doSomethingAndLogIt("Test", () => multiplyIt(5));
will already do what you are after. When the delegate is called, the parameter 5 will be passed in as well. Why? Because the callee will call your delegate, and you will call the method multiply with the argument 5.
Here is a quick test.
It isn't possible to do that as of the current version of C#, here's why...
Let's take your example (fake syntax)
public int MultiplyIt(int value)
{
//Do something that has side-effects
}
public void SomeMethod(Action<int> someAction<int>)
{
//Do something
someAction();
}
Now let's create an override of that method:
public void SomeMethod(int someValue)
{
//Do something
}
Now you call it:
SomeMethod(multiplyIt(5))
Which one does the compiler call?
Lets say you don't overload it (or that for some reason the compiler shouts an error if you do, but it is legal).
What then is the difference between these two calls?
SomeMethod(multiplyIt(5));
SomeMethod(() => multiplyIt(5));
Technically the first one runs multiplyIt before passing its value to SomeMethod. The second one multiplyIt may never be called, or it may alter something and then call it. That is an important distinction. If you add in some method to call it without the () => part, the developer can't know, without reading documentation, how the method call (and the action) are called. Is it a normal method call? The "special" delegate case? Who knows.
The () => isn't that much of a price to pay to be able to read a method and understand that you are passing in a delegate vs a value.

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 adding a break in a while loop resolve overload ambiguity?

Consider this Reactive Extensions snippet (ignore the practicality of it):
return Observable.Create<string>(async observable =>
{
while (true)
{
}
});
This does not compile with Reactive Extensions 2.2.5 (using NuGet Rx-Main package). It fails with:
Error 1 The call is ambiguous between the following methods or properties: 'System.Reactive.Linq.Observable.Create<string>(System.Func<System.IObserver<string>,System.Threading.Tasks.Task<System.Action>>)' and 'System.Reactive.Linq.Observable.Create<string>(System.Func<System.IObserver<string>,System.Threading.Tasks.Task>)'
However, adding a break anywhere in the while loop fixes the compilation error:
return Observable.Create<string>(async observable =>
{
while (true)
{
break;
}
});
The problem can be reproduced without Reactive Extensions at all (easier if you want to try it without fiddling with Rx):
class Program
{
static void Main(string[] args)
{
Observable.Create<string>(async blah =>
{
while (true)
{
Console.WriteLine("foo.");
break; //Remove this and the compiler will break
}
});
}
}
public class Observable
{
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, Task> subscribeAsync)
{
throw new Exception("Impl not important.");
}
public static IObservable<TResult> Create<TResult>(Func<IObserver<TResult>, Task<Action>> subscribeAsync)
{
throw new Exception("Impl not important.");
}
}
public interface IObserver<T>
{
}
Ignoring the Reactive Extensions part of it, Why does adding break help the C# compiler resolve the ambiguity? How can this be described with the rules of overload resolution from the C# specification?
I'm using Visual Studio 2013 Update 2 targeting 4.5.1.
It's easiest to just pull out async as well as the lambdas here, as it emphasizes what's going on. Both of these methods are valid and will compile:
public static void Foo()
{
while (true) { }
}
public static Action Foo()
{
while (true) { }
}
However, for these two methods:
public static void Foo()
{
while (true) { break; }
}
public static Action Foo()
{
while (true) { break; }
}
The first compiles, and the second does not. It has a code path that doesn't return a valid value.
In fact, while(true){} (along with throw new Exception();) is an interesting statement in that it is the valid body of a method with any return type.
Since the infinite loop is a suitable candidate for both overloads, and neither overload is "better", it results in an ambiguity error. The non-infinite loop implementation only has one suitable candidate in overload resolution, so it compiles.
Of course, to bring async back into play, it is actually relevant in one way here. For the async methods they both always return something, whether it's a Task or a Task<T>. The "betterness" algorithms for overload resolution will prefer delegates that return a value over void delegates when there is a lambda that could match either, however in your case the two overload both have delegates that return a value, the fact that for async methods returning a Task instead of a Task<T> is the conceptual equivalent of not returning a value isn't incorporated into that betterness algorithm. Because of this the non-async equivalent wouldn't result in an ambiguity error, even though both overloads are applicable.
Of course it's worth noting that writing a program to determine if an arbitrary block of code will ever complete is a famously unsolvable problem, however, while the compiler cannot correctly evaluate whether every single snippet will complete, it can prove, in certain simple cases such as this one, that the code will in fact never complete. Because of this there are ways of writing code that will clearly (to you and me) never complete, but that the compiler will treat as possibly completing.
Leaving async out of this to start with...
With the break, the end of the lambda expression is reachable, therefore the return type of the lambda has to be void.
Without the break, the end of the lambda expression is unreachable, so any return type would be valid. For example, this is fine:
Func<string> foo = () => { while(true); };
whereas this isn't:
Func<string> foo = () => { while(true) { break; } };
So without the break, the lambda expression would be convertible to any delegate type with a single parameter. With the break, the lambda expression is only convertible to a delegate type with a single parameter and a return type of void.
Add the async part and void becomes void or Task, vs void, Task or Task<T> for any T where previously you could have any return type. For example:
// Valid
Func<Task<string>> foo = async () => { while(true); };
// Invalid (it doesn't actually return a string)
Func<Task<string>> foo = async () => { while(true) { break; } };
// Valid
Func<Task> foo = async () => { while(true) { break; } };
// Valid
Action foo = async () => { while(true) { break; } };

Use func method for an action also?

I created a method to abstract try/catch functionality. I have about 30 methods that have this exact same try/catch scenario. So I put it in one method:
private T Invoke<T>(Func<T> func)
{
try
{
return func.Invoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
Now, most of the methods call it like this:
public IEnumerable<PingResponse> GetAllForPingRequest(PingRequest pingRequest)
{
return Invoke(() => PingResponseLogic.GetAllForPingRequest(pingRequest));
}
My issue is that I have just a couple of methods that call it without needing to return a value:
Invoke<void>(() => CustomVariableGroupLogic.Delete(customVariableGroup));
However, I can't use void there. The Invoke() method takes a func, but in this case it needs to be an action. I did some research and it looks like I may have to create another Invoke() method, but have it take an action. Those suggestions were from 2009 and 2010 though. Is it possible to somehow use my func method without having to create another Invoke() method like Invoke2()?
One quick and dirty solution would be to add default value after calling Delete method. It will be ignored anyway, if you don't assign result of the Invoke method to a variable. For instance, next code demonstrates this:
Invoke(() => {CustomVariableGroupLogic.Delete(customVariableGroup); return 0; });
You can see similar example proposed here,
If you have lots and lots of such calls, you can build a fancy wrapper, that will return Func for a given Action. Example:
Func<Action, Func<int>> wrap = action => () => {action(); return 0;};
now you can
Invoke(() => wrap(() => CustomVariableGroupLogic.Delete(customVariableGroup)));
but this goes a little bit close to lambda craziness
Inspired by pcm2:
you can create an overload to Invoke, that simply takes Action as a parameter, use solution proposed above to call implementation with Func<T>:
public void Invoke(Action action)
{
Invoke(() => {action(); return 0;});
}
now you simply can
Invoke(() => CustomVariableGroupLogic.Delete(customVariableGroup));
Could you not just create an overload of invoke?
public void Invoke<T>(Func<T> func){
return (T) InvokeInternal(func);
}
public void Invoke(Action action){
InvokeInternal(action);
}
If you'd then want both methods to do the exact same thing, and keeping things DRY, you could create a method like so:
private object InvokeInternal(System.Delegate #delegate)
{
try
{
return #delegate.DynamicInvoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
And have both your overloads calling this method, appropriately casting the result, if any
Do you really have to func.Invoke()? Why not just func()?
Why isn't your Invoke static?
Depending on what LogAndThrowFaultException is doing, this could be pretty bad. Make sure that the exception stack is preserved by always setting the inner exception to ex.
But yes, you need a second function that returns void instead of T.
You can wrap the action into a func like so. Or you can create a convenience function that does the wrapping:
void Main()
{
Action<string> a = s => Console.WriteLine(s);
Invoke(() => { a(); return null; });
Invoke(s);
}
private void Invoke(Action a)
{
Invoke(() => { a(); return null; };
}

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

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...
}

Categories

Resources