47

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?

testing
  • 19,681
  • 50
  • 236
  • 417
  • possible duplicate of [Cannot implicitly convert type from Task<>](http://stackoverflow.com/questions/12886559/cannot-implicitly-convert-type-from-task) – i3arnon Sep 08 '14 at 20:21

5 Answers5

91

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());
}
takemyoxygen
  • 4,294
  • 22
  • 19
13

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());
NeddySpaghetti
  • 13,187
  • 5
  • 32
  • 61
  • I also have a try/catch block to catch the exceptions and I'm showing a spinner. So my method name is correct than? – testing Sep 08 '14 at 11:45
  • yes i think it should be OK, starting a new thread is not ideal but i think the guideline is more about calling a synchronous version of the function inside `Task.Run` – NeddySpaghetti Sep 09 '14 at 09:35
9

Works for me:

List<Item> list = Task.Run(() => manager.GetList()).Result;

in this way it is not necessary to mark the method with async in the call.

7

you can use the following

private async Task<List<string>> GetItems()
{
    return await Task.FromResult(new List<string> 
    { 
      "item1", "item2", "item3" 
    });
}
Lloyd
  • 257
  • 3
  • 6
3

Instead of doing all these, one can simply use ".Result" to get the result from a particular task, e.g.:

List<Item> list = GetListAsync().Result;

Which as per the definition => Gets the result value of this Task <TResult>

EvilDr
  • 8,943
  • 14
  • 73
  • 133
avinava basu
  • 119
  • 4