我有这样的方法:
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;
}
但我只是想知道它是否真的async
,因为我认为该部分list.Add(await request.GetResult());
和return list;
打破了该方法的async
性质。
如果我错了,请纠正我,如果我是对的,我该如何解决?
更新:根据我的理解,我必须这样C# 5.0 async await return a list return await Task.Run(() => new List<string>() {"a", "b"});
,但不知道如何将其应用于我的案例。
答案 0 :(得分:4)
您的方法是异步的,但可能无法充分利用资源。
你的方法将做的是进入foreach
循环,创建MyRequestAsync
对象,然后(在await
点)它将放弃其线程,直到结果可用。一旦结果可用,将找到一个适当的线程,该方法将继续运行。它会将结果添加到list
并返回到循环的顶部,并反复重复整个过程。
但是,考虑到这一点 - 如果这些请求是独立的,您可以相反地并行生成每个请求,然后只有在所有请求完成后才继续运行您的方法。那将是这样的:
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
}
而且,对于愚蠢的观点,你可以重写整个方法:
return await Task.WhenAll(from l in links select new RequestAsync(l).GetResult());
但这可能会降低其可读性。
答案 1 :(得分:1)
在我看来,I / O是async
所以可以调用方法&#34;真的是异步&#34;。
async
用于I / O在等待某些东西时不阻塞线程(这里是结果),而不是在它执行某些操作时#34; (这里是list.Add)。
答案 2 :(得分:0)
这是不可能的,因为你所说的任何东西都可能是阻塞操作。如果某个地方隐藏了阻塞操作,此方法也会阻塞。如果您想使方法无阻塞和/或仅使用可扩展的异步IO,您必须检查您所做的和您调用的所有内容。
这表示您的代码看起来像是非阻止的,因为它使用await
(而不是Task.Wait
)。稍微简化一下,这个方法将返回第一个await
操作,这可能是需要的。