【问题标题】:Async controller action with loop带循环的异步控制器动作
【发布时间】:2012-11-21 23:00:35
【问题描述】:

我将如何编写一个由 1 +n 个异步调用 (await) 组成的异步控制器操作?例如。假设我需要首先检索对象Foo,它具有可变数量的Bars 标识符,我需要获取所有这些实体(为了这个问题,没有fetchBarsByFooId。我会使用@ 987654325@ 或者Parallel.For

public async Task<ActionResult> Bars(int id) {
    Foo foo = await this.FooProvider.GetFooAsync(id);
    var bars = new ConcurrentQueue<Bar>();

    // Sub-optimal version
    foreach (int barId in foo.BarIDs) {
        Bar bar = this.BarProvider.GetBar(barId);
        bars.Enqueue(bar)
    }

    // Fetch each bar asynchronously and pass them to the view.
    ....

    return View(bars.ToArray());
}

【问题讨论】:

    标签: asp.net-mvc async-await


    【解决方案1】:

    嗯,首先要解决的问题是您是否真的想要并行性,或者只是异步性。只是异步很简单:

    var bars = new List<Bar>();
    foreach (var id in foo.Bars)
    {
        bars.Add(await BarProvider.GetBarAsync(id));
    }
    return View(bars);
    

    对于并行性,您可以使用Task.WhenAll:

    var tasks = foo.Bars.Select(id => BarProvider.GetBarAsync(id));
    var bars = await Task.WhenAll(tasks);
    return View(bars);
    

    (我意识到这是比非并行版本更短的代码 - 但它在概念上更棘手。)

    你应该使用Parallel.ForTask.WaitAll,因为这两个都是阻塞调用 - 而Task.WhenAll返回你一个任务,当所有的子任务已完成。

    【讨论】:

    • 今晚我会在回家的火车上试试这个,然后再接受你的回答,但这看起来不错。
    • 抱歉耽搁了,我花了一段时间才将所有代码库移植到任务并行库。这很好用!
    • @Oli: 太好了 :) Async/await 真的很棒 :)
    猜你喜欢
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 2018-06-28
    • 2014-08-04
    • 2017-03-18
    相关资源
    最近更新 更多