将生成 IEnumerable<T> 的 TransformBlock 链接到接收 T 的块
Posted
技术标签:
【中文标题】将生成 IEnumerable<T> 的 TransformBlock 链接到接收 T 的块【英文标题】:Link TransformBlock producing IEnumerable<T> to block that receives T 【发布时间】:2018-11-13 17:17:20 【问题描述】:我正在编写一个网络图库scraper,我想尽可能地使用 TPL 数据流并行处理文件。
为了抓取,我首先获取画廊主页并解析 html 以获取图像页面链接作为列表。然后我转到列表中的每个页面并解析 HTML 以获取指向图像的链接,然后将其保存到磁盘。
这是我的程序的大纲:
var galleryBlock = new TransformBlock<Uri, IEnumerable<Uri>>(async uri =>
// 1. Get the page
// 2. Parse the page to get the urls of each image page
return imagePageLinks;
);
var imageBlock = new TransformBlock<Uri, Uri>(async uri =>
// 1. Go to the url and fetch the image page html
// 2. Parse the html to retrieve the image url
return imageUri;
);
var downloadBlock = ActionBlock<Uri>(async uri =>
// Download the image from uri to list
);
var opts = new DataflowLinkOptions PropagateCompletion = true;
galleryBlock.LinkTo(imageBlock, opts); // this doesn't work, as I'm returning a list and not a single Item. However I want to progress that block in parallel.
imageBlock.LinkTo(downloadBlock, opts);
【问题讨论】:
问题是什么? 他想知道如何将单个 url 发送到操作块,但是 transformBlock 正在返回一个列表,所以 linkTo 不工作,因为不想要一个列表 如果我理解正确,只需将TransformBlock
替换为TransformManyBlock
。
我冒昧地重新命名了您的问题。我希望这是一个适当的改变。
【参考方案1】:
您可以使用TransformManyBlock
代替您的TransformBlock
:
var galleryBlock = new TransformManyBlock<Uri, Uri>(async uri =>
return Enumerable.Empty<Uri>(); //just to get it compiling
);
var imageBlock = new TransformBlock<Uri, Uri>(async uri =>
return null; //just to get it compiling
);
var opts = new DataflowLinkOptions PropagateCompletion = true ;
galleryBlock.LinkTo(imageBlock, opts); // bingo!
【讨论】:
我刚做晚饭,你打败了我!,点赞,数据流很棒 我也是(心脏)数据流。 TPL 的无名英雄。 所以,如果我正确理解了您的答案,TransformManyBlock
需要 1 项并产生 n?
@Ruhrpottpatriot 正确。具体来说,TransformManyBlock<TIn,TOut>
接受一个返回 IEnumerable<TOut>
的委托,并分别提供每个 IEnumerable<TOut>
中的每个 TOut
项目。它与 LINQ SelectMany
非常相似。
嗯...我一直认为SelectMany
是一种扁平化列表的方法,即IEnumerable<TList>
-> TList
。以上是关于将生成 IEnumerable<T> 的 TransformBlock 链接到接收 T 的块的主要内容,如果未能解决你的问题,请参考以下文章
如何将两个 IEnumerable<T> 连接成一个新的 IEnumerable<T>?
无法将类型“IEnumerable<T>”隐式转换为“ActionResult<IEnumerable<T>>”
如何将多个 IEnumerable<IEnumerable<T>> 列表添加到 IEnumerable<List<int>>