sam95
sam95

Reputation: 119

How can I use the Task.Run(Func<Task> f) method signature?

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

Answers (4)

D Stanley
D Stanley

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 the async and await keywords. It is not intended to be called directly from user code.

Upvotes: 7

Johnathon Sullinger
Johnathon Sullinger

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

David
David

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

dcastro
dcastro

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

Related Questions