7

Ich habe den folgenden Code mit einem Produzenten-Thread und mehreren Consumer-Threads. Weißt du, ob mehrere Verbraucher threadsicher sind? Zum Beispiel gibt es eine Chance, dass Thread 1 verbraucht und während dieser Thread 2 parallel verbrauchen und den Wert des Elements, das in Thread 1 verwendet wird, ändern?BlockingCollection mehrere Verbraucher

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; } 
} 
} 

Vielen Dank im Voraus

Antwort

1

Sobald Sie ein Element verbraucht haben, wird es aus der Sammlung entfernt, so dass kein anderer Thread darauf zugreifen kann (zumindest durch die Sammlung).

Dieser Cache sieht eher wie ein Puffer für mich. Was fügt es noch zusätzlich zur Blockierungssammlung hinzu? Es ist seltsam, dass der Cache seine eigenen Elemente konsumieren könnte.

+0

Danke. Du hast recht. Es ist ein Puffer. Die Namen sind irrelevant. Das Szenario, das ich fragen wollte, ist, ob es eine Chance gibt, dass Thread 1 verbraucht und dabei Thread 2 parallel verbraucht und den Wert des Elements ändert, das in Thread 1 verwendet wird, denn wie Sie sehen können, rufe ich Consumer dreimal an in parallel (Button1_Click-Ereignis) – pantonis

+0

Dann ist die Antwort nein, es gibt keine Chance, aber weil verschiedene Threads die gleichen Elemente nicht verbrauchen können. Brauchen Sie die verschiedenen Threads, um auf alle Elemente in der Sammlung zuzugreifen? Wenn das der Fall ist, können Sie die GetConsumingEnumerable() -Methode nicht verwenden. – fsimonazzi

+0

Nein. Ich möchte mehrere Verbraucher haben, die den Puffer so schnell wie möglich verbrauchen. Also wird jede Manipulation, die in der foreach-Schleife auf Thread 1 des 'item'-Objekts vorgenommen wird, nicht durch Thread 2 verändert? Denn wie Sie sehen können, ist die Consume-Methode statisch. – pantonis

0

A Blocking Blöcke nur die Sammlung selbst. Nicht die Objekte in der Liste.

Verwandte Themen