Create Task without lambda - c#

Trying to pass function instead lambda expression and finally mixed up why line:
int t2 = await Task.Run( ()=>Allocate2() );
not raises error. This lambda expression ()=>Allocate2() not returns Task. Why no error?
How to create task without lambda expression with function Allocate?
static async void Example()
{
int t = await Task.Run(Allocate);
int t2 = await Task.Run( ()=>Allocate2() );
Console.WriteLine("Compute: " + t);
}
static Task<int> Allocate()
{
return 1;
}
static int Allocate2()
{
return 1;
}

Task.Run() wants you to pass a parameterless Action or Func to it.
A lambda can be assigned to an Action or a Func (as appropriate) which is why calling Task.Run() with a lambda works for you.
If you don't want to use a lambda, you must explicitly create an Action or a Func, passing the method you want to call to the constructor of the Action or the Func.
The following demonstrates:
static void Main()
{
var task = Task.Run(new Action(MyMethod));
}
static void MyMethod()
{
Console.WriteLine("MyMethod()");
}
OR:
static void Main()
{
var task = Task.Run(new Func<int>(MyMethod));
}
static int MyMethod()
{
Console.WriteLine("MyMethod()");
return 42;
}
Note that this doesn't work if the method needs one or more parameters. In that event, you must use a lambda.

Related

Cast Task<T> to Task<object> in C# without having T

I have static class full of extension methods where each of the methods is asynchronous and returns some value - like this:
public static class MyContextExtensions{
public static async Task<bool> SomeFunction(this DbContext myContext){
bool output = false;
//...doing stuff with myContext
return output;
}
public static async Task<List<string>> SomeOtherFunction(this DbContext myContext){
List<string> output = new List<string>();
//...doing stuff with myContext
return output;
}
}
My goal is to be able to invoke any of these methods from a single method in another class and return their result as an object. It would look something like this:
public class MyHub: Hub{
public async Task<object> InvokeContextExtension(string methodName){
using(var context = new DbContext()){
//This fails because of invalid cast
return await (Task<object>)typeof(MyContextExtensions).GetMethod(methodName).Invoke(null, context);
}
}
}
The problem is that the cast fails. My dilemma is that I cannot pass any type parameters to the "InvokeContextExtension" method because it is part of a SignalR hub and is invoked by javascript. And to a certain extent I don't care about the return type of the extension method because it is just going to get serialized to JSON and sent back to the javascript client. However I do have to cast the value returned by Invoke as a Task in order to use the await operator. And I have to supply a generic parameter with that "Task" otherwise it will treat the return type as void. So it all comes down to how do I successfully cast Task with generic parameter T to a Task with a generic parameter of object where T represents the output of the extension method.
You can do it in two steps - await the task using the base class, then harvest the result using reflection or dynamic:
using(var context = new DbContext()) {
// Get the task
Task task = (Task)typeof(MyContextExtensions).GetMethod(methodName).Invoke(null, context);
// Make sure it runs to completion
await task.ConfigureAwait(false);
// Harvest the result
return (object)((dynamic)task).Result;
}
Here is a complete running example that puts in context the above technique of calling Task through reflection:
class MainClass {
public static void Main(string[] args) {
var t1 = Task.Run(async () => Console.WriteLine(await Bar("Foo1")));
var t2 = Task.Run(async () => Console.WriteLine(await Bar("Foo2")));
Task.WaitAll(t1, t2);
}
public static async Task<object> Bar(string name) {
Task t = (Task)typeof(MainClass).GetMethod(name).Invoke(null, new object[] { "bar" });
await t.ConfigureAwait(false);
return (object)((dynamic)t).Result;
}
public static Task<string> Foo1(string s) {
return Task.FromResult("hello");
}
public static Task<bool> Foo2(string s) {
return Task.FromResult(true);
}
}
In general, to convert a Task<T> to Task<object>, I would simply go for the straightforward continuation mapping :
Task<T> yourTaskT;
// ....
Task<object> yourTaskObject = yourTaskT.ContinueWith(t => (object) t.Result);
(documentation link here)
However, your actual specific need is to invoke a Task by reflection and obtain its (unknown type) result .
For this, you can refer to the complete dasblinkenlight's answer, which should fit your exact problem.
I'd like to provide an implementation which is IMHO the best combination of the earlier answers:
precise argument handling
no dynamic dispatch
general purpose extension method
Here you go:
/// <summary>
/// Casts a <see cref="Task"/> to a <see cref="Task{TResult}"/>.
/// This method will throw an <see cref="InvalidCastException"/> if the specified task
/// returns a value which is not identity-convertible to <typeparamref name="T"/>.
/// </summary>
public static async Task<T> Cast<T>(this Task task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
if (!task.GetType().IsGenericType || task.GetType().GetGenericTypeDefinition() != typeof(Task<>))
throw new ArgumentException("An argument of type 'System.Threading.Tasks.Task`1' was expected");
await task.ConfigureAwait(false);
object result = task.GetType().GetProperty(nameof(Task<object>.Result)).GetValue(task);
return (T)result;
}
You cannot cast Task<T> to Task<object>, because Task<T> is not covariant (it's not contravariant, either). The simplest solution would be to use some more reflection:
var task = (Task) mi.Invoke (obj, null) ;
var result = task.GetType ().GetProperty ("Result").GetValue (task) ;
This is slow and inefficient, but usable if this code is not executed often. As an aside, what is the use of having an asynchronous MakeMyClass1 method if you are going to block waiting for its result?
and Another possibility is to write an extension method to this purpose:
public static Task<object> Convert<T>(this Task<T> task)
{
TaskCompletionSource<object> res = new TaskCompletionSource<object>();
return task.ContinueWith(t =>
{
if (t.IsCanceled)
{
res.TrySetCanceled();
}
else if (t.IsFaulted)
{
res.TrySetException(t.Exception);
}
else
{
res.TrySetResult(t.Result);
}
return res.Task;
}
, TaskContinuationOptions.ExecuteSynchronously).Unwrap();
}
It is none-blocking solution and will preserve original state/exception of the Task.
The most efficient approach would be custom awaiter:
struct TaskCast<TSource, TDestination>
where TSource : TDestination
{
readonly Task<TSource> task;
public TaskCast(Task<TSource> task)
{
this.task = task;
}
public Awaiter GetAwaiter() => new Awaiter(task);
public struct Awaiter
: System.Runtime.CompilerServices.INotifyCompletion
{
System.Runtime.CompilerServices.TaskAwaiter<TSource> awaiter;
public Awaiter(Task<TSource> task)
{
awaiter = task.GetAwaiter();
}
public bool IsCompleted => awaiter.IsCompleted;
public TDestination GetResult() => awaiter.GetResult();
public void OnCompleted(Action continuation) => awaiter.OnCompleted(continuation);
}
}
with the following usage:
Task<...> someTask = ...;
await TaskCast<..., object>(someTask);
The limitation of this approach is that the result is not a Task<object> but an awaitable object.
I made a little extension method based on dasblinkenlight's answer:
public static class TaskExtension
{
public async static Task<T> Cast<T>(this Task task)
{
if (!task.GetType().IsGenericType) throw new InvalidOperationException();
await task.ConfigureAwait(false);
// Harvest the result. Ugly but works
return (T)((dynamic)task).Result;
}
}
Usage:
Task<Foo> task = ...
Task<object> = task.Cast<object>();
This way you can change T in Task<T> to anything you want.
For the best approach, without using reflection and dynamic ugly syntax, and without passing generic types. I would use two extension methods for achieving this goal.
public static async Task<object> CastToObject<T>([NotNull] this Task<T> task)
{
return await task.ConfigureAwait(false);
}
public static async Task<TResult> Cast<TResult>([NotNull] this Task<object> task)
{
return (TResult) await task.ConfigureAwait(false);
}
Usage:
Task<T1> task ...
Task<T2> task2 = task.CastToObject().Cast<T2>();
This my second approach, but not recommended:
public static async Task<TResult> Cast<TSource, TResult>([NotNull] this Task<TSource> task, TResult dummy = default)
{
return (TResult)(object) await task.ConfigureAwait(false);
}
Usage:
Task<T1> task ...
Task<T2> task2 = task.Cast((T2) default);
// Or
Task<T2> task2 = task.Cast<T1, T2>();
This my third approach, but not recommended: (similar to second one)
public static async Task<TResult> Cast<TSource, TResult>([NotNull] this Task<TSource> task, Type<TResult> type = null)
{
return (TResult)(object) await task.ConfigureAwait(false);
}
// Dummy type class
public class Type<T>
{
}
public static class TypeExtension
{
public static Type<T> ToGeneric<T>(this T source)
{
return new Type<T>();
}
}
Usage:
Task<T1> task ...
Task<T2> task2 = task.Cast(typeof(T2).ToGeneric());
// Or
Task<T2> task2 = task.Cast<T1, T2>();
This is not a good idea to mix await with dynamic/reflection invoke since await is a compiler instruction that generates a lot of code around invoked method and there is no real sense to "emulate" compiler work with more reflections, continuations, wrappers and etc.
Since what you need is to manage your code at RUN TIME then forget the asyc await syntax sugar which works at compile time. Rewrite SomeFunction and SomeOtherFunction without them, and start operations in your own tasks created at run time. You will get the same behavior but with crystal clear code.

Delegate that returns a delegate

I'm trying to create a delegate that will return a delegate. I then want to invoke this delegate, and also invoke the returned inner delegate. My question is: Why is this causing an error? And how to I change this code to accomplish what I'm trying to do?
The error message is 'Method name expected'.
delegate string del();
delegate Delegate nestedDel();
public static void main()
{
nestedDel myNestedDel = () =>
{
del myInnerDel = () => { return "inside"; };
return myInnerDel;
};
Delegate k = myNestedDel();
k(); // Error!!!
}
In short, you've messed up the types. One of the delegates should return the other one, so its return type should simply be the type of the other delegate. In your code example:
delegate string del();
delegate Delegate nestedDel();
you are in fact returning a delegate, but Delegate or MulticastDelegate are just infrastructure base classes and are not invocable directly. By using these classes you're losing information about list of parameters and return values, so simple call() operator cannot work. As Lee mentioned in comments, you could do it by k.DynamicInvoke() but that's.. overkill. Just use a proper type name instead of Delegate.
Working example:
delegate string InnerDel();
delegate InnerDel OuterDel(); // this one returns an instance of Inner delegate
public static void Main()
{
OuterDel myOuterDelegate = () =>
{
InnerDel myInnerDel = () => { return "inside"; };
return myInnerDel;
};
InnerDel k = myOuterDelegate();
k();
}
Personally, I like Func/Actions more than defining my own delegate classes... at least as long as they have at most few parameters. In terms of func/action it would look like this:
public static void Main()
{
Func<Func<string>> myOuterDelegate = () =>
{
Func<string> myInnerDel = () => { return "inside"; };
return myInnerDel;
};
var k = myOuterDelegate();
k();
}
or even..
public static void Main()
{
Func<Func<string>> myOuterDelegate = () => () => { return "inside"; };
var k = myOuterDelegate();
k();
}
Your error is because instances of the Delegate type cannot be invoked with the function call syntax i.e. as k();.
You can call it using DynamicInvoke:
string s = (string)k.DynamicInvoke();
obviously this is prone to runtime errors so a better approach would be to change the return type of nestedDel e.g.
delegate Func<string> nestedDel();
nestedDel myNestedDel = () =>
{
Func<string> myInnerDel = () => { return "inside"; };
return myInnerDel;
};
stringk = myNestedDel();

How to call an Asynchronous Method in the background of a Xamarin application

I have a method which I would like to call in the background of xamarin application my application.
I wrote something like this
public partial class App : Application
{
private static Stopwatch stopWatch = new Stopwatch();
protected override void OnStart()
{
if (!stopWatch.IsRunning)
{
stopWatch.Start();
}
Device.StartTimer(new TimeSpan(0, 0, 1), () =>
{
if (stopWatch.IsRunning && stopWatch.Elapsed.Minutes== 2)
{
await myMethod() //This is the method which return a threat I would like to call
stopWatch.Restart();
}
});
}
}
My Method is something like this:
public async static Task <Mytype> myMethod()
{
MyType myType;
myType= await SomeMethod();
return myType;
}
When I add async to my the method like this
protected async override void OnStart()
I receive this error
The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
When I add the asynchronous lambda expression like this,
Device.StartTimer(new TimeSpan(0, 0, 1), async () =>
I now received this error
Cannot convert async lambda expression to delegate type 'Func<bool>'. An async lambda expression may return void, Task or Task<T>, none of which are convertible to 'Func<bool>'.
What could be the problem and how can I fix this?
Assuming myMethod is returning a Task, i.e.:
async Task myMethod()
{
Debug.WriteLine("Processing something....");
await Task.Delay(1); // replace with what every you are processing....
}
Then you can call Device.StartTimer in the OnCreate like this:
Device.StartTimer(new TimeSpan(0, 0, 1), () =>
{
if (stopWatch.IsRunning && stopWatch.Elapsed.Minutes == 2)
{
myMethod().ContinueWith((Task t) =>
{
stopWatch.Restart();
return true;
});
}
return true;
});

Best way to define a method which can accept an Action or a Func delegate

I would like to introduce a method/function which can receive an Action or a Func<T>, and depending on what it got, it should return void or T.
Now I have to write this method in two, almost same versions like this.
public void WrapAction(Action action) {
// do something...
action();
// do something more...
}
public T WrapFunc(Func<T> func) {
// do something...
var result = func();
// do something more...
return result;
}
Is there any technique to avoid this repetition?
In contrast, for example in Javascript I have the flexibility to accept any kind of a function (may be void) and just return it's result, and if it was void, then it will return undefined. But in C# one cannot write something like Func<void>.
What about to make an Func<bool> out of an action via an extension method and reduce the wrapper to handle Func<T> only.
public static class ActionExtensions
{
public static Func<bool> ToFunc(this Action action)
{
return () =>
{
action();
return true;
};
}
}
Then WrapAction could simply call WrapFunc.
public void WrapAction(Action action)
{
WrapFunc(action.ToFunc());
}
Or remove WrapAction at all and use WrapFunc directly.
WrapFunc(action.ToFunc());
One possible solution is that you can extract the repeating bits out to separate methods in the same class so, something like this...
public void WrapAction(Action action) {
DoInitialBit();
action();
DoFinalBit();
}
public T WrapFunc(Func<T> func) {
DoInitialBit();
var result = func();
DoFinalBit();
return result;
}
private void DoInitialBit()
{
// Do the thing before you call the Action or Func
}
private void DoFinalBit()
{
// Do the thing after you call the Action or Func
}
Obviously, you may have to take inputs or return outputs from these additional methods as required but that's the general gist of it.
Some really ugly code to have code DRY:
static void Main(string[] args)
{
var p = new Program();
p.WrapAction(() => Console.WriteLine(123));
Console.WriteLine(p.WrapFunc<string>(() => "321"));
Console.ReadKey();
}
public void WrapAction(Action action) => WrapActionInner<object>(action);
public T WrapFunc<T>(Func<T> func) => WrapActionInner<T>(func);
private T WrapActionInner<T>(object action)
{
if (action is Action)
{
((Action)action)();
return default(T);
}
return ((Func<T>)action)();
}
The idea is to wrap functionality into type unsafe private method.

How to create Task with multiple params, return typ, TaskCreationOptions param by using new keyword?

How can i create new task with multiple params, return type and createoptions by using new?
Task<int> task = Task<int>(DoWork(0,1));
private static Task<int> DoWork(int a, int b)
{
return null;
}
this is working fine.... but when i try create task with new keyword so i can set startoptions to longrunning like this:
Task<int> task = new Task<int>(DoWork(0,1), TaskCreationOptions.LongRunning);
I am always getting some errs like:
Argument 1: cannot convert from 'System.Threading.Tasks.Task' to 'System.Func'
I tried xx different variants but no luck. I understand i am probably wrongly passing param "Func function". I would like to avoid anonymous function. thx.
You can pass the method as a Lambda Expression:
Task<Task<int>> task = new Task<Task<int>>(() => DoWork(0,1), TaskCreationOptions.LongRunning);
Although, it is recommended to use Task.Factory.StartNew if possible, so you return a Hot Task instead of a Cold Task (which required you to call Task.Start).
Task<Task<int>> task = Task.Factory.StartNew(() => DoWork(0,1), TaskCreationOptions.LongRunning);
public SomeClass()
{
var func = new Func<int, int, int>((i1, i2) => i1 + i2);
Task.Factory.StartNew(() =>
Debug.WriteLine(func(1, 2)), TaskCreationOptions.LongRunning);
Task.Factory.StartNew(() =>
Debug.WriteLine(DoWork(2, 3).Result), TaskCreationOptions.LongRunning);
}
private static Task<int> DoWork(int a, int b)
{
return Task.FromResult(a + b);
}
The constructor for Task<T> requires a Func<T> argument.
Task<int> task = Task<int>(DoWork(0,1));
is attempting to call the DoWork method and pass the returnedTask<int> as the parameter into the task task. You need to pass a Func<int> instead by changing the type of DoWork to:
private static int DoWork(int a, int b) { ... }
then you can do:
Task<int> task = new Task<int>(() => DoWork(0,1), TaskCreationOptions.LongRunning);

Categories

Resources