【问题标题】:Using async and collections使用异步和集合
【发布时间】:2014-05-10 14:26:48
【问题描述】:

我希望使用 httpclient 下载大量文件,对它们执行一些耗时但不昂贵的计算,然后在运行一些显示它不存在的查询后将结果添加到我的数据库中。

我如何在概念上做到这一点(只是等待的位置等会有所帮助)

我目前有以下:

获取地址列表 添加(等待网页下载,然后继续处理)到任务列表 foreach 列表的元素,等待它,然后将其添加到数据库中。

但是,这似乎本质上是串行运行的。

这应该怎么设计?

【问题讨论】:

    标签: .net entity-framework async-await c#-5.0


    【解决方案1】:

    我会使用TPL Dataflow 建立一个管道。您发布地址和演员是:

    1. 网页下载
    2. 处理中
    3. 添加到数据库

    尽可能使用async(只要操作是真正异步的)并设置一个较高的MaxDegreeOfParallelism以允许TPL自行选择最佳值。

    【讨论】:

    • 您的意思是使用它提供的原语(actionblock、bufferblock 等)还是其他?如果你的意思是原语,你能解释一下哪些是原语吗?我对 TPL 一点也不熟悉。
    • 嗯,是的。最简单的方法是对所有这些都使用 ActionBlock。你只需要给它一个方法(例如WebPageDownload)并记住最后将它“发送”到下一个ActionBlock。更“正确”的方法是也使用 TransformBlocks
    • 有没有一种好方法可以让链中后面的 trasformblock 发布到链中较早的转换块?
    • @soandos 它没有技术问题。它只需要引用前面的块。但如果你这样做了,它就不再是一个简单的管道,而且你有一个连续循环的危险。
    • 但是我在循环什么? download.InputCount != 0 && Download.OutputCount != 0 && process.OutputCount != 0 && process.InputCount != 0(循环的)正确吗?
    【解决方案2】:

    我会让下载/处理并行运行并等待它们全部完成。代码看起来像这样:

    // get a collection of "hot" Tasks running in parallel
    var tasks = myCollection.Select(x => DownloadAndProcessAsync(x));
    
    // await the completion of all Tasks
    await Task.WhenAll(tasks);
    

    【讨论】:

    • 没有必要等待所有任务完成后再继续已经完成的工作
    • lambda 中的方法旨在下载并执行单个项目的所有处理。更新了方法名称以反映这一点。
    猜你喜欢
    • 1970-01-01
    • 2017-04-20
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2015-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多