我的方法真的是异步吗?

时间:2014-04-17 12:47:50

标签: c# asynchronous c#-5.0 async-await

我有这样的方法:

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"});,但不知道如何将其应用于我的案例。

3 个答案:

答案 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操作,这可能是需要的。