2012-06-21 156 views
2

这段代码有什么问题,或者这可以更有效地完成吗?特别是,我有点担心parrallel.foreach发射/调用委托内的代码。这可能会导致任何问题? 我问,因为目前消费者无法跟上正在生产的物品在很多情况下,导致内存问题。Parallel.Foreach委托调用另一个委托

public delegate void DataChangedDelegate(DataItem obj); 

public class Consumer 
{ 
    public DataChangedDelegate OnCustomerChanged; 
    public DataChangedDelegate OnOrdersChanged; 

    private CancellationTokenSource cts; 
    private CancellationToken ct; 
    private BlockingCollection<DataItem> queue; 

    public Consumer(BlockingCollection<DataItem> queue) { 
     this.queue = queue; 
     Start(); 
    } 

    private void Start() { 
     cts = new CancellationTokenSource(); 
     ct = cts.Token; 
     Task.Factory.StartNew(() => DoWork(), ct); 
    } 

    private void DoWork() { 

     Parallel.ForEach(queue.GetConsumingPartitioner(), item => { 
      if (item.DataType == DataTypes.Customer) { 
       OnCustomerChanged(item); 
      } else if(item.DataType == DataTypes.Order) { 
       OnOrdersChanged(item); 
      } 
     }); 
    } 
} 
+0

是否有多个消费者实例创建?如果是,为什么不只有一个静态实例处理队列? –

+0

没有一个实例... – mike01010

回答

2

特别是,我有点担心/ parrallel.foreach烧制中的代码调用的委托。这可能会导致任何问题?

一般而言,从Parallel.ForEach方法中调用委托没有任何问题。

但是,它确实使控制线程安全性变得更加困难,因为委托将承担正确处理所有数据同步的要求。这主要是一个问题,因为使用委托的主要原因是允许您调用的“方法”被传入,这意味着它是从外部提供的。

这意味着,例如,如果委托人碰巧调用试图更新用户界面的代码,则可能会遇到麻烦,因为它将从后台/ ThreadPool线程调用。

+0

谢谢。期望上面的消费者无限期地处理被循环加入的队列是不合理的(没有延迟......即真的非常快)?我基本上试图测试消费者是否能够跟上这种(罕见)的情况。到目前为止,他们不能,并最终耗尽内存。 – mike01010

+0

@ mike01010非常多 - 除非你有多个消费者。分区/调度开销永远不会匹配您在固定循环中添加项目的速度......所以您最终会落后。你需要对添加进行一些限制,或者对多个消费者进行处理...... –

+0

即时消息不确定这会有所帮助..没有并行.foreach假设尝试根据需要产生线程(有效地做同样的事情,多个消费者会)? – mike01010