Προγραμματισμός

Πώς να εργαστείτε με το BlockingCollection στο C #

Εξετάστε ένα σενάριο όπου πολλά νήματα διαβάζουν και γράφουν σε μια ουρά. Πιο συγκεκριμένα, ενδέχεται να έχετε ταυτόχρονα πολλούς παραγωγούς που αποθηκεύουν δεδομένα και πολλούς καταναλωτές να τα ανακτούν από ένα κοινό κατάστημα δεδομένων. Ως εκ τούτου, θα χρειαστείτε έναν κατάλληλο μηχανισμό συγχρονισμού για να συγχρονίσετε την πρόσβαση σε αυτά τα δεδομένα.

Εδώ είναι ακριβώς που η κατηγορία BlockingCollection έρχεται στη διάσωση. Αν και υπάρχουν πολλοί άλλοι τρόποι, αυτή η τάξη παρέχει έναν από τους πιο αποτελεσματικούς τρόπους συγχρονισμού της πρόσβασης στα δεδομένα σας. Η κλάση BlockingCollection ανήκει στο χώρο ονομάτων System.Collections.Current.

Τι είναι το BlockingCollection;

Το BlockingCollection είναι μια συλλογή ασφαλών νημάτων στην οποία μπορείτε να έχετε πολλά νήματα να προσθέτουν και να αφαιρούν ταυτόχρονα δεδομένα. Αντιπροσωπεύεται στο .Net μέσω της κλάσης BlockingCollection. μπορείτε να χρησιμοποιήσετε αυτήν την τάξη για να εφαρμόσετε ένα μοτίβο παραγωγού-καταναλωτή.

Στο μοτίβο παραγωγού-καταναλωτή, έχετε δύο ξεχωριστά στοιχεία που λειτουργούν σε δύο διαφορετικά νήματα. Αυτά περιλαμβάνουν ένα στοιχείο παραγωγού που παράγει ορισμένα δεδομένα που ωθούνται στην ουρά και έναν καταναλωτή που καταναλώνει τα δεδομένα που είναι αποθηκευμένα στην ουρά. Όταν χρησιμοποιείτε ένα BlockingCollection, μπορείτε να καθορίσετε την οριακή χωρητικότητα καθώς και τον τύπο της συλλογής που θέλετε να χρησιμοποιήσετε.

Ο τύπος BlockingCollection λειτουργεί ως περιτύλιγμα σε μια παρουσία τύπου IProducerConsumerCollection. Με άλλα λόγια, λειτουργεί ως περιτύλιγμα πάνω σε μια άλλη συλλογή η οποία με τη σειρά της εφαρμόζει τη διεπαφή IProducerConsumerCollection. Για παράδειγμα, οι κλάσεις ConcurrentBag, ConcurrentQueue και ConcurrentStack μπορούν να χρησιμοποιηθούν με ένα BlockingCollection, καθώς όλα εφαρμόζουν τη διεπαφή IProducerConsumerCollection.

Σημειώστε ότι η διεπαφή IProducerConsumerCollection περιέχει δήλωση μεθόδων που μπορούν να χρησιμοποιηθούν για να λειτουργούν με συλλογές ασφαλείς για νήματα. Το MSDN δηλώνει: "Καθορίζει μεθόδους για χειρισμό συλλογών που είναι ασφαλείς για νήματα που προορίζονται για χρήση παραγωγού / καταναλωτή. Αυτή η διεπαφή παρέχει μια ενοποιημένη αναπαράσταση για συλλογές παραγωγών / καταναλωτών, έτσι ώστε υψηλότερου επιπέδου αφαιρέσεις όπως System.Collections.Concurrent.BlockingCollection να χρησιμοποιεί τη συλλογή ως τον υποκείμενο μηχανισμό αποθήκευσης. "

Το παρακάτω απόσπασμα κώδικα δείχνει πώς μπορείτε να δημιουργήσετε μια παρουσία ενός BlockingCollection των συμβολοσειρών.

var blockingCollection = νέο BlockingCollection ();

Όταν χρησιμοποιείτε ένα BlockingCollection, μπορείτε να προσθέσετε δεδομένα στη συλλογή είτε χρησιμοποιώντας τη μέθοδο Προσθήκη ή τη μέθοδο TryAdd. Ας καταλάβουμε τώρα τη διαφορά μεταξύ αυτών των δύο μεθόδων.

Δεδομένα BlockingCollection = νέο BlockingCollection (boundedCapacity: 3);

δεδομένα. Προσθήκη (1);

δεδομένα. Προσθήκη (2);

δεδομένα. Προσθήκη (3);

δεδομένα. Προσθήκη (4); // Αυτό θα μπλοκάρει μέχρι να αφαιρεθεί ένα στοιχείο από τη συλλογή.

Σημειώστε τον τρόπο με τον οποίο καθορίσαμε το boundedCapacity κατά τη δημιουργία μιας παρουσίας του BlockingCollection όπως φαίνεται στο απόσπασμα κώδικα που δίνεται παραπάνω. Αυτό καθορίζεται για να υποδείξει το περιορισμένο μέγεθος της παρουσίας συλλογής.

Μπορείτε επίσης να χρησιμοποιήσετε τη μέθοδο TryAdd για να προσθέσετε ένα στοιχείο σε μια παρουσία BlockingCollection. Σε αυτήν τη μέθοδο, μπορείτε να χρησιμοποιήσετε μια τιμή χρονικού ορίου. Εάν η λειτουργία προσθήκης αποτύχει εντός του καθορισμένου χρόνου, η μέθοδος TryAdd επιστρέφει false. Το παρακάτω απόσπασμα κώδικα δείχνει πώς μπορείτε να επωφεληθείτε από τη μέθοδο TryAdd για να προσθέσετε ένα στοιχείο σε μια παρουσία του BlockingCollection.

Δεδομένα BlockingCollection = νέο BlockingCollection (boundedCapacity: 3);

δεδομένα. Προσθήκη (1);

δεδομένα. Προσθήκη (2);

δεδομένα. Προσθήκη (3);

εάν (data.TryAdd (4, TimeSpan.FromMilliseconds (100)))

{

Console.WriteLine ("Ένα νέο στοιχείο προστέθηκε με επιτυχία στη συλλογή.");

}

αλλού

{

Console.WriteLine ("Αποτυχία προσθήκης νέου στοιχείου στη συλλογή.");

}

Για να αφαιρέσετε ένα στοιχείο από το BlockingCollection, μπορείτε να χρησιμοποιήσετε τη μέθοδο Take ή TryTake. Σημειώστε ότι η μέθοδος Λήψη αποκλείει εάν δεν υπάρχουν στοιχεία στη συλλογή και ξεμπλοκάρετε αμέσως μόλις προστεθεί ένα νέο στοιχείο στη συλλογή. Η μέθοδος TryTake μπορεί επίσης να χρησιμοποιηθεί για την κατάργηση ενός αντικειμένου από μια παρουσία ενός BlockingCollection. Μπορείτε να καθορίσετε μια τιμή χρονικού ορίου με αυτήν τη μέθοδο, έτσι ώστε η μέθοδος να αποκλείει (έως ότου παρέλθει ο καθορισμένος χρόνος) έως ότου προστεθεί ένα στοιχείο στη συλλογή. Εάν δεν ήταν δυνατή η κατάργηση ενός αντικειμένου από τη συλλογή κατά τη διάρκεια αυτής της περιόδου (καθορίστηκε το χρονικό όριο), η μέθοδος TryTake επιστρέφει false.

Το ακόλουθο απόσπασμα κώδικα δείχνει πώς μπορεί να χρησιμοποιηθεί η μέθοδος TryTake για την κατάργηση ενός αντικειμένου από μια παρουσία τύπου BlockingCollection.

int αντικείμενο?

ενώ (data.TryTake (στοιχείο, TimeSpan.FromMilliseconds (100)))

{

Console.WriteLine (στοιχείο);

}

Ακολουθεί μια πλήρης λίστα κωδικών για την αναφορά σας. Αυτό το πρόγραμμα δείχνει πώς μπορείτε να χρησιμοποιήσετε ένα BlockingCollection για να προσθέσετε και να αφαιρέσετε αντικείμενα από και προς μια συλλογή.

Πρόγραμμα τάξης

   {

ιδιωτικά στατικά δεδομένα BlockingCollection = νέο BlockingCollection ();

ιδιωτικός παραγωγός στατικού κενού ()

       {

για (int ctr = 0; ctr <10; ctr ++)

           {

δεδομένα. Προσθήκη (ctr);

Νήμα. Sleep (100);

           }

       }

ιδιωτικός στατικός κενός καταναλωτής ()

       {

foreach (στοιχείο var στα δεδομένα.GetConsumingEnumerable ())

           {

Console.WriteLine (στοιχείο);

           }

       }

static void Main (συμβολοσειρά [] args)

       {

var produser = Task.Factory.StartNew (() => Παραγωγός ());

var καταναλωτής = Task.Factory.StartNew (() => Consumer ());

Κονσόλα. Διαβάστε ();

       }

   }

$config[zx-auto] not found$config[zx-overlay] not found