To use this method :
public static Task Run(Action action)
I just write :
void MyMethod(){ //do something }
Task t = Task.Run(new Action(MyMethod));
However I do not understand how to use the following overload
public static Task Run(Func<Task> f)
The msdn mentions that the returned task is "a proxy for the task returned by f" which is even more confusing to me. What is meant by proxy and how would I call this method?
The Run method allows you to create and execute a task in a single method call and is a simpler alternative to the StartNew method. It creates a task with the following default values: Its cancellation token is CancellationToken.
To start a task in C#, follow any of the below given ways. Use a delegate to start a task. Task t = new Task(delegate { PrintMessage(); }); t. Start();
Task<T> also represents an operation which might be in progress, or might have been cancelled, faulted, or might have completed. However, a completed Task<T> will contain the result of that operation, which you can then read.
TResult. The type of the return value of the method that this delegate encapsulates. This type parameter is covariant. That is, you can use either the type you specified or any type that is more derived. For more information about covariance and contravariance, see Covariance and Contravariance in Generics.
Func<Task>
is simply a function that returns a task. That task is then executed.
So Task Run( Func<Task> f )
returns a Task
, whose job is to run another Task
(the one created by f
). That's what's meant by a "proxy".
However, read the Note on MSDN (emphasis added):
The
Run<TResult>(Func<Task<TResult>>)
method is used by language compilers to support theasync
andawait
keywords. It is not intended to be called directly from user code.
Func<T>
is a generic delegate - here's its full signature:
public delegate TResult Func<out TResult>()
As you can see, it represents a function that takes no parameters, and returns an instance of type TResult
. In the case of Func<Task>
, TResult
is Task
.
What this means, is that you can do this:
public Task MyAsyncMethod() { ... }
Task.Run(MyAsyncMethod);
This converts your method MyAsyncMethod
into a delegate of type Func<Task>
and passes it to Task.Run
. It's syntactic sugar for Task.Run( new Func<Task>(MyAsyncMethod) );
The msdn mentions that the returned task is "a proxy for the task returned by f" which is even more confusing to me (what is meant by proxy ?)
What this means is that Task.Run
will simply wrap the task returned by MyAsyncMethod
is another Task
.
That signature allows you to provide a method that returns a Task, when you run Task.Run
. That is because the last generic argument of a Func<T>
is the return value given back by the delegate you provide. Meaning:
public Func<bool> IsValid = this.ValidateUser;
public bool ValidateUser() { return someUser.IsAuthenticated; }
or even just
public Func<bool> IsValidUser = this.User.IsAuthenticated;
Then you can use the delegate as you would any other method, and the delegate will return a bool.
public void Foo()
{
if (!IsValidUser()) throw new InvalidOperationException("Invalid user");
}
You can use parameters that are passed in to the delegate, by providing additional generic types other than the return value.
Func<int, bool> IsUserAgeValid = (age) => return age > 18;
// Invoke the age check
bool result = this.IsUserAgeValid(17);
The thing to remember is that the last generic is always the return type in a Func. If only one generic is provided, then there is no parameters, only a return type.
A Func<Task>
allows you to use an awaitable
method in your Task.Run
call.
This also means that you can await
from within the anonymous delegate you provide.
public Task Foo()
{
/* .. do stuff */
}
public void Bar()
{
Task.Run(async () =>
{
await Foo();
/* do additional work */
});
}
and if you don't need to await the call to Foo()
, you can just give Task.Run
the Foo
method.
Task.Run(Foo);
If you find yourself wanting to await the awaitable method given to Task.Run
as shown above, it is probably better that you use ContinueWith
.
public void Bar()
{
Task.Run(Foo).ContinueWith(foosTaskResult =>
{
/* Do stuff */
});
}
The MSDN documentation saying the the Task returned is a proxy for the Task of f, basically means that
Task returnedTask = Task.Run(Foo);
will set returnedTask
to be the Task that was returned by the call to the awaitable Foo()
method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With