Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return list from async/await method

I want to make a webservice request asynchron. I call it here:

List<Item> list = GetListAsync(); 

Here is the declaration of my function, which should return a list:

private async Task<List<Item>> GetListAsync(){     List<Item> list = await Task.Run(() => manager.GetList());     return list; } 

If I want to compile I get the following error

Cannot implicitely convert type System.Threading.Tasks.Task<System.Collections.Generic.List<Item>> to System.Collections.Generic.List<Item> 

As I know If I use the async modifier the result is automatically wrapped with Task. I think this doesn't happen because I use Task.Run. If I remove the Task.Run(() => part I get

Cannot await System.Collections.Generic.List expression

I think I haven't fully understood the async/await methods. What I'm doing wrong?

like image 271
testing Avatar asked Sep 08 '14 09:09

testing


People also ask

What is the return type of async await?

The behavior of async / await is similar to combining generators and promises. Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.

Is an async method that returns task?

An async method typically returns a Task or a Task<TResult>. Inside an async method, an await operator is applied to a task that's returned from a call to another async method. You specify Task<TResult> as the return type if the method contains a return statement that specifies an operand of type TResult .

What is the return type of async async?

Async methods can have the following return types: Task<TResult>, for an async method that returns a value. Task, for an async method that performs an operation but returns no value. void, for an event handler. Starting with C# 7.0, any type that has an accessible GetAwaiter method.

How to get result of a method in async?

A method returns Task<T> can use await keyword to get its Result. If you mark your method as async, compiler will build a special helper class to get every Result on another thread, so it will not block your UI. (So any async method is a class, in fact, but the compiler will get everything done to make it looks like a method to you.)

Should I return a task or task<T> with async methods?

Most of the time, you should just use a return type of Task or Task<T> with async methods. Everything else in the list above is for specific situations that are not very common. If anything, you have a choice between returning Task and returning void. But even that choice is lopsided, heavily favoring the use of Task. Why?

Why is it bad to return a void from an async?

Even more problematic is that the caller can't handle exceptions properly when it does not await an async method. There are a few valid reasons for returning void from an async method, but the vast majority of the time you should return a Task so you can await it.


2 Answers

You need to correct your code to wait for the list to be downloaded:

List<Item> list = await GetListAsync(); 

Also, make sure that the method, where this code is located, has async modifier.

The reason why you get this error is that GetListAsync method returns a Task<T> which is not a completed result. As your list is downloaded asynchronously (because of Task.Run()) you need to "extract" the value from the task using the await keyword.

If you remove Task.Run(), you list will be downloaded synchronously and you don't need to use Task, async or await.

One more suggestion: you don't need to await in GetListAsync method if the only thing you do is just delegating the operation to a different thread, so you can shorten your code to the following:

private Task<List<Item>> GetListAsync(){     return Task.Run(() => manager.GetList()); } 
like image 144
takemyoxygen Avatar answered Sep 21 '22 11:09

takemyoxygen


In addition to @takemyoxygen's answer the convention of having a function name that ends in Async is that this function is truly asynchronous. I.e. it does not start a new thread and it doesn't simply call Task.Run. If that is all the code that is in your function, it will be better to remove it completely and simply have:

List<Item> list = await Task.Run(() => manager.GetList()); 
like image 27
NeddySpaghetti Avatar answered Sep 20 '22 11:09

NeddySpaghetti