1

I have method like that:

public async Task<IEnumerable<Model>> Get([FromUri]IList<string> links)
{
    IList<Model> list = new List<Model>();
    foreach (var link in links)
    {
        MyRequestAsync request = new MyRequestAsync(link);
        list.Add(await request.GetResult());
    }

    return list;
}

But I am just wondering if it is really async because I am thinking that part list.Add(await request.GetResult()); and return list; breaking the async nature of the method.

Please correct me if I am wrong and if I am right how can I fix that?

UPDATED: for my understanding I have to so something like that C# 5.0 async await return a list return await Task.Run(() => new List<string>() {"a", "b"}); but not sure how to apply that for my case.

Community
  • 1
  • 1
Sergino
  • 10,128
  • 30
  • 98
  • 159
  • 4
    I think you may not understand what async actually *means*. This [blog post](http://blogs.msdn.com/b/ericlippert/archive/2010/10/29/asynchronous-programming-in-c-5-0-part-two-whence-await.aspx) by Eric Lippert is where I usually recommend people start reading to understand the `async` and `await` keywords. – Damien_The_Unbeliever Apr 17 '14 at 12:51

3 Answers3

4

Your method is async, but may not be making the best use of resources.

What your method will do is enter the foreach loop, create the MyRequestAsync object, and then (at the await point) it will give up its thread until the result becomes available. Once the result is available, an appropriate thread will be found and the method will resume running. It will add the result to list and go back to the top of the loop, and repeat this whole process over and over.

But, consider this - if these requests are independent, you could, instead, make each of the requests in parallel, and then only continue running your method once all of the requests are complete. That would be something like:

public async Task<IEnumerable<Model>> Get([FromUri]IList<string> links)
{
    IList<Task<Model>> list = new List<Task<Model>>();
    foreach (var link in links)
    {
        MyRequestAsync request = new MyRequestAsync(link);
        list.Add(request.GetResult());
    }

    return new List<Model>(await Task.WhenAll(list));
    //Or just
    //return await Task.WhenAll(list);
    //Since we don't need to return a list
}

And, for silly points, you could re-write the whole method as:

return await Task.WhenAll(from l in links select new RequestAsync(l).GetResult());

But that may make it less readable.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
1

In my opinion the I/O is async so the method can be called "really async".
async is meant for I/O to not block the thread when it is waiting for something (here the result), but not when it is "doing something" (here the list.Add).

Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
0

That's kind of impossible to tell because anything you call could be a blocking operation. If there's a blocking operation hidden somewhere this method will block as well. If you want to make a method non-blocking and/or only use scalable async IO you must review everything that you do and that you call.

That said your code looks like it is non-blocking because it uses await (instead of, say, Task.Wait). Simplifying things a bit, this method will return on the first await operation which is probably what do need.

usr
  • 168,620
  • 35
  • 240
  • 369
  • The code just working on `debug` but when `not on debug` I am not getting any result(i think I am getting dead lock) because for my understanding `return list;` not waiting until `list.Add(await request.GetResult());` completed – Sergino Apr 17 '14 at 13:00
  • It does wait. That's the point of `await`. It pauses the method until the given task has completed. Use the debugger to inspect the list at runtime. Find out why it is not filled correctly. – usr Apr 17 '14 at 13:07
  • Not getting any errors on debug. Asked the related question here http://stackoverflow.com/questions/23134243/async-issue-when-changed-method-to-use-collection – Sergino Apr 17 '14 at 13:17