Reputation: 119
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?
Upvotes: 9
Views: 5765
Reputation: 152521
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.
Upvotes: 7
Reputation: 7414
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.
Upvotes: 1
Reputation: 10708
a Func<T>
refers to a method which returns T
, which in this case is a Task
. Thus, to make MyMethod
compatible with this particular overload, you would write
Task MyMethod() {...}
Which also means you could make MyMethod
and async
method, thus
async Task MyMethod() {...}
When referring to a "proxy" this means that the Task
returned by Task.Run
isn't actually the task returned by MyMethod
, but instead wraps it.
Upvotes: 0
Reputation: 68660
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
.
Upvotes: 1