2012-11-02 149 views
7

我有以下代码与一个生产者线程和多个消费者线程。你知道多个消费者是否线程安全。例如,是否有线程1消耗的可能性,并且线程2并行使用并更改线程1中使用的项目的值?BlockingCollection多个消费者

namespace BlockingColl 
{ 
public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     try 
     { 
      for (int i = 0; i < 3; i++) 
      { 

       ThreadPool.QueueUserWorkItem((x) => 
        { 
         foreach (var item in bc.GetConsumingEnumerable()) 
         { 
          Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " - " + item + " - " + DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff tt")); 
         } 
        }); 
      } 
     } 
     catch (Exception) 
     { 

      throw; 
     } 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     for (int i = 0; i < 3; i++) 
     { 

      ThreadPool.QueueUserWorkItem((x) => 
       { 
        Cache.Consume(); 
       }); 
     } 


     for (int i = 0; i < 50000; i++) 
     { 
      Cache.bc.TryAdd(new Client() { ClientId = i, ClientName = "Name" + i }); 
     } 
    } 
} 

static class Cache 
{ 
    public static BlockingCollection<Client> bc = new BlockingCollection<Client>(); 


    public static void Consume() 
    { 
     foreach (var item in bc.GetConsumingEnumerable()) 
     { 
      Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " - " + item + " - " + DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff tt")); 
     } 
    } 
} 

public class Client 
{ 
    public int ClientId { get; set; } 
    public string ClientName { get; set; } 
} 
} 

感谢事先只

回答

1

一旦你消耗了一个元素,它就会从集合中移除,所以没有其他线程能够访问它(至少通过集合)。

该缓存对我来说更像是一个缓冲区。无论如何,它在阻塞集合上添加了什么?奇怪的是,缓存将能够消耗自己的元素。

+0

谢谢。你是对的。这是一个缓冲区。名字是无关紧要的。我想问的情景是,当线程1消耗并且在线程2并行使用并更改线程1中使用的项目的值时,是否有任何机会,因为您可以看到我称为消费者三次并行(Button1_Click事件) – pantonis

+0

然后答案是否定的,没有机会,但因为不同的线程不能消耗相同的元素。你需要不同的线程来访问集合中的所有元素吗?如果是这种情况,则不能使用GetConsumingEnumerable()方法。 – fsimonazzi

+0

不,我想要的是让多个消费者尽快消费缓冲区。所以在'item'对象的Thread 1的foreach循环中所做的任何操作都不会被Thread 2修改?因为你可以看到Consume方法是静态的。 – pantonis

0

一个BlockingCollection块集合本身。不是列表中的对象。

相关问题