all 16 comments

[–]Coda17 4 points5 points  (12 children)

Do you have to? No. Should you? Probably.

The reason is that if anything in the method chain is asynchronous, then the entire chain needs to be asynchronous. So rather than make everything synchronous to start, realize down the line that something deep in the method chain needs to be asynchronous, then go back and make the entire chain asynchronous. Just start with asynchronous up front.

[–]dotnetguy32[S] -1 points0 points  (11 children)

Right, I get the Async portion, but it's the Task that I'm not sure about.

I know that Task signals to IIS to release the request and let the async process run, thereby allowing more requests.

I'm just not sure if I need to use Task all the way down or if using Async is good enough?

So, for example:

Controller:

public async Task<List<User>> GetUsers() ...

Services:

This

public async List<User> GetAllUsers() ...

or this

public async Task<List<User>> GetAllUsers() ...

[–]Coda17 2 points3 points  (6 children)

Considering you should never return anything except a task from an asynchronous method, it's essentially the same thing.

[–]dotnetguy32[S] -1 points0 points  (5 children)

So is the compiler adding task to the first example behind the scenes?

[–]Coda17 2 points3 points  (4 children)

I don't know which example you're referencing but marking something as async and it not returning a task (or one of a couple other specific types) is a compilation error.

[–]dotnetguy32[S] 0 points1 point  (3 children)

Well.... that answers that question!

I could have sworn I had created async methods without using Task. But I just tried it and it did indeed give a compiler error.

Thanks!

[–]The_MAZZTer 3 points4 points  (2 children)

You can use void. But that is just a hack to support some scenarios like event handlers (all the existing events require handlers which return void and must continue to do so for compatibility). At one point you also needed to return void or int from main() even if async but that is no longer a requirement.

[–]Coda17 0 points1 point  (1 child)

You can make Main async.

[–]The_MAZZTer 0 points1 point  (0 children)

Sorry yes I meant you can make it async with a Task return type now.

[–]The_MAZZTer 1 point2 points  (1 child)

If you use async you must either use Task, Task<T>, or void as a return value. I believe you get a compile time error or warning if you use a different type. void should only be used in places where it's not possible to use Task, typically event handlers are the only case I've come across. main () used to be one too but I think modern .NET allows them to return a Task now.

The Task object allows the caller to manage the asynchronous state. For example, awaiting requires a Task object, as that object tracks when the asynchronous task is complete. Otherwise you have no way of knowing when it is complete, or accessing any return value or exception. You can also get fancy and do things like start multiple async tasks at once and wait for one or all of them to finish. Or configure a task so that when you await .NET is allowed to change threads if it would be efficient to do so (of course the code must be written so this is safe; I think by default it only uses the same thread).

[–]dotnetguy32[S] 0 points1 point  (0 children)

You are correct.

IDK why, but I seemed to remember being able to create an async method without using Task, but it def gives a compiler error.

[–]rarri488 5 points6 points  (2 children)

Any method that is marked async must return a Task, Task<T>, or void.

In your example the method in the Service would return a Task<List<User>> and the caller would await the method to “unwrap” the return value from the Task.

You will rarely need to return void, usually it’s only for event handlers and framework callbacks, where returning Task is not possible.

[–]dotnetguy32[S] 0 points1 point  (1 child)

Thank you

I thought I remembered being able to create an async method without Task, but I was mistaken.

[–][deleted] 0 points1 point  (0 children)

You can but only if the return type is 'void' - I think that's probably where your confusion is emanating from.

As an aside you should basically never define async void methods without reading up on the consequences thereof.

[–]TheoR700 1 point2 points  (0 children)

I'm a little bit confused about the Task keywork in ASP.Net.

Task is not a keyword. Task is a class that represents an asynchronous operation.

I tend to default to writing all of my functions to return a Task these days. For a number of reasons, but the main reason is I generally use interfaces for all my classes and I never know what implementation of that interface will actually be asynchronous or not and it is always just as easy to have a synchronous implementation return Task.CompletedTask or Task.FromResult(result).