如何从并行任务产生在.NET 4.5 [英] How to yield from parallel tasks in .NET 4.5

查看:132
本文介绍了如何从并行任务产生在.NET 4.5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用.NET迭代器并行任务/等待?事情是这样的:

I would like to use .NET iterator with parallel Tasks/await?. Something like this:

IEnumerable<TDst> Foo<TSrc, TDest>(IEnumerable<TSrc> source)
{
    Parallel.ForEach(
        source,
        s=>
        {
            // Ordering is NOT important
            // items can be yielded as soon as they are done                
            yield return ExecuteOrDownloadSomething(s);
        }
}

不幸的是.NET本身不能处理这个问题。最好的答案迄今@svick - 使用进行AsParallel()

Unfortunately .NET cannot natively handle this. Best answer so far by @svick - use AsParallel().

奖金:任何简单的异步/等待code实现多个出版商和单个用户?订户将产生,而酒吧将处理。 (唯一的核心库)

BONUS: Any simple async/await code that implements multiple publishers and a single subscriber? The subscriber would yield, and the pubs would process. (core libraries only)

推荐答案

这似乎是对PLINQ工作:

This seems like a job for PLINQ:

return source.AsParallel().Select(s => ExecuteOrDownloadSomething(s));

此将并行使用线程的数量有限,只要它完成每个结果返回执行委托

This will execute the delegate in parallel using a limited number of threads, returning each result as soon as it completes.

如果在 ExecuteOrDownloadSomething()方法IO的限制(例如,它实际上是下载的东西),你不想浪费线程,然后使用异步 - 等待可能是有意义的,但它会更复杂

If the ExecuteOrDownloadSomething() method is IO-bound (e.g. it actually downloads something) and you don't want to waste threads, then using async-await might make sense, but it would be more complicated.

如果你想充分利用的异步,你不应该返回的IEnumerable ,因为它是同步的(也就是说,它阻止如果没有项目可用)。你需要的是某种形式的异步集合,你可以使用 ISourceBlock (具体的 TransformBlock )由TPL数据流为:

If you want to fully take advantage of async, you shouldn't return IEnumerable, because it's synchronous (i.e. it blocks if no items are available). What you need is some sort of asynchronous collection, and you can use ISourceBlock (specifically, TransformBlock) from TPL Dataflow for that:

ISourceBlock<TDst> Foo<TSrc, TDest>(IEnumerable<TSrc> source)
{
    var block = new TransformBlock<TSrc, TDest>(
        async s => await ExecuteOrDownloadSomethingAsync(s),
        new ExecutionDataflowBlockOptions
        {
            MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
        });

    foreach (var item in source)
        block.Post(item);

    block.Complete();

    return block;
}

如果来源是慢(即要开始处理来自的结果美孚()迭代前完成后),您可能需要移动的foreach 完成()打电话给一个单独的任务。甚至更好的解决办法是让 ISourceBlock&LT;台橡方式&gt;

If the source is "slow" (i.e. you want to start processing the results from Foo() before iterating source is completed), you might want to move the foreach and Complete() call to a separate Task. Even better solution would be to make source into a ISourceBlock<TSrc> too.

这篇关于如何从并行任务产生在.NET 4.5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆