处理Thread执行yield return函数的值

时间:2017-06-30 14:18:08

标签: c# multithreading asynchronous async-await

我是多线程的新手,我正在尝试以一种方式创建一个枚举器,因为它已经准备好了,但它会继续在后台处理。

我希望能够使用这样的最终类:

library(dplyr)
library(pander)

data.frame(a = sample(LETTERS, 10), 
           b = sample(LETTERS, 10)) %>%
  slice(n()-5:n()) %>% 
  pander()

但是我想让它在while循环中继续获取下一个结果。

评论:不能并行处理,因为每个结果都取决于之前的结果。

我想到可能有一个结果的队列,并且有一个线程在获取结果的同时返回队列中的第一个结果,但是我无法使其工作。这是我的尝试,但我不知道该做什么 while (await asyncEnumerator.MoveNextAsync()) { T result = asyncEnum.Current; //Do Something }

我更新了代码

MoveNext()

显然,如果有更好的方法,我想知道,我是多线程新手。

1 个答案:

答案 0 :(得分:4)

  

但是我想让它在while循环中继续获取下一个结果。

普通的异步枚举器在这里是错误的解决方案。调查员是一种“拉动”技术;他们只在消费代码请求下一个项目时才做。

从“生产者”和“消费者”的角度考虑您的问题。如果生产者只在消费者请求它时才工作,那么你有一个枚举器场景。在您的情况下,您希望生产者独立生成项目,因此枚举器不适合。

一个选项是reactive extensions; observable表示类似于枚举器的值序列,除了可观察量是一种“推”技术。因此,生产者将价值推向消费者,消费者会对新的价值作出反应(因此称为反应性)。

听起来Rx非常适合你,但确实有很高的学习曲线。

更简单的选项可能是使用更传统的生产者/消费者队列。由于您希望异步使用它,因此您需要一个与异步兼容的生产者/消费者队列。 BufferBlock<T>one solutionAsyncProducerConsumerQueue<T>my AsyncEx library

在这两种情况下,你都会开始制作人,然后消费:

var queue = new BufferBlock<T>();

// Kick off producer
var producer = Task.Run(() =>
{
  while (...)
  {
    T value = ...;
    queue.Post(value);
  }
  queue.Complete();
});

// Consumer code
while (await queue.OutputAvailableAsync())
{
  var value = await queue.ReceiveAsync();
  ...
}

最终,您需要await producer任务,以便您可以正确检测生产者代码中的任何异常。