سؤال

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.

هل كانت مفيدة؟

المحلول

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.

نصائح أخرى

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).

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top