TPL-减少发布延迟

时间:2018-07-10 00:15:39

标签: c# .net task-parallel-library

我正在构建一个网络爬虫,看来TPL非常适合我的用例。这是我想到的流程:

GetCommentsFromA --|                     |-- NotifyC
                   |-- ExtractKeywords --| 
GetCommentsFromB --|                     |-- NotifyD

基本上,组件有三种类型:收集器,转换器和通知器。收集者通过抓取不同的网站来收集评论,然后将评论传递给转换器。他们应该每X秒轮询一次网页。在这种情况下,唯一存在的转换器就是负责从注释中提取关键字的转换器。他们本质上是永无休止的生产者。

我最初是通过扩展经典的Producer-Consumer模型来实现的。我在收集器和转换器之间放置了一个缓冲块,在转换器和通知程序之间放置了一个缓冲块。 (实际上还有更多事情在发生,但这是事实。)每个组件都独立地发布和接收来自其相应缓冲区的数据。就是说,我觉得必须有一个更优雅的方法。

从那时起,我发现LinkTo允许块相互连接,并且除了缓冲块之外还有专门的块,因此我开始考虑以下方面:

var extractKeywords = new TransformBlock<string, string>(ExtractKeywords);
var notifyTarget = new ActionBlock<string, string>(NotifyTarget);
extractKeywords.LinkTo(notifyTarget);

然后我可以启动不同的收集器,或多或少在单独的线程上执行以下操作:

public async Task CollectAsync()
{
    while (true)
    {
        Page page = await website.DownloadLatestPageAsync();
        foreach (string comment in page.Comments())
        {
            transformer.Post(comment);
        }
        await Task.Delay(ArbitraryDelay);
    }
}

收集器将发布到前面的代码段中看到的转换块。但是,我确实对此方法有所保留。首先,(这可能是由于我对异步,多线程和TPL缺乏了解),我担心发布到转换块会导致延迟。理想情况下,我希望收集者花费尽可能少的时间将数据传输到转换器,但是我似乎无法找出一种干净的方法。如果转换器变慢,则调用Post似乎会阻塞一段时间,而且我不确定SendAsync是否也可以解决此问题。 Task.Run似乎是个坏主意……但我不知道。感觉就像我接近了,但是错过了一些简单的事情。

0 个答案:

没有答案