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

Πώς να συνεργαστείτε με το ConcurrentBag και το ConcurrentDictionary στο .Net

Ταυτόχρονες συλλογές στο .Net περιέχονται στο System.Collections.Current namespace και παρέχουν εφαρμογές χωρίς κλειδαριά και ασφαλείς για νήματα των κλάσεων συλλογής. Οι συλλογές ασφαλών νημάτων παρουσιάστηκαν για πρώτη φορά στο .Net 4 και οι συλλογές εισήχθησαν αρχικά ως μέρος του .Net Framework 1.0 και ήταν διαθέσιμες στο χώρο ονομάτων System.Collections.

Μπορείτε να επωφεληθείτε από τις ταυτόχρονες συλλογές για να εργαστείτε με συλλογές χωρίς να χρειάζεται να γράψετε επιπλέον κώδικα για συγχρονισμό νήματος. Μπορείτε να ρίξετε μια ματιά στο άρθρο μου σχετικά με το ConcurrentStack και το ConcurrentQueue.

Ταυτόχρονη τσάντα

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

  • Προσθήκη (στοιχείο T) - Αυτή η μέθοδος χρησιμοποιείται για την προσθήκη ενός στοιχείου στο ConcurrentBag.
  • TryPeek (out T) - Αυτή η μέθοδος χρησιμοποιείται για την ανάκτηση ενός στοιχείου από το ConcurrentBag χωρίς να το αφαιρέσετε.
  • TryTake (out T) - Αυτή η μέθοδος χρησιμοποιείται για την ανάκτηση ενός στοιχείου από το ConcurrentBag. Σημειώστε ότι αυτή η μέθοδος καταργεί το στοιχείο από τη συλλογή.

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

ConcurrentBag concurrentBag = νέο ConcurrentBag ();

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

    {

concurrentBag.Add (i);

    }

Εάν επρόκειτο να ανακτήσετε τα στοιχεία της συλλογής, θα πρέπει να γράψετε τον ακόλουθο κωδικό:

ενώ (concurrentBag.Count> 0)

  {

Στοιχείο Int32;

εάν (concurrentBag.TryTake (στοιχείο έξω))

       {

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

       }

  }

Σημειώστε πώς έχει χρησιμοποιηθεί η μέθοδος TryTake: Επιστρέφει αληθινή στην επιτυχία, ψευδώς διαφορετικά. Η μέθοδος TryTake καταργεί επίσης το στοιχείο από τη συλλογή. Ο βρόχος while συνεχίζει την εκτέλεση έως ότου ο αριθμός των στοιχείων στη συλλογή είναι μεγαλύτερος από το μηδέν. Ακολουθεί η πλήρης λίστα κωδικών για την αναφορά σας.

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

        {

ConcurrentBag concurrentBag = νέο ConcurrentBag ();

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

            {

concurrentBag.Add (i);

            }

ενώ (concurrentBag.Count> 0)

            {

Στοιχείο Int32;

εάν (concurrentBag.TryTake (στοιχείο έξω))

                {

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

                }

            }

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

        }

Ταυτόχρονη έκδοση

Το Λεξικό είναι μια γενική συλλογή ζευγών κλειδιών / τιμών. Είναι γρηγορότερο από ένα Hashtable, καθώς εξαλείφει τα γενικά έξοδα του μποξ και του un-boxing. Το ConcurrentDictionary περιέχεται στο χώρο ονομάτων System.Collections.Currurrent και αντιπροσωπεύει ένα λεξικό ασφαλές για νήματα.

Τα σημαντικά μέλη της κλάσης ConcurrentDictionary περιλαμβάνουν τα ακόλουθα:

  • TryAdd: Αυτή η μέθοδος χρησιμοποιείται για την προσθήκη ενός στοιχείου στην παρουσία ConcurrentDictionary. Σημειώστε ότι αυτή η μέθοδος δημιουργεί μια εξαίρεση εάν το κλειδί υπάρχει ήδη στη συλλογή.
  • TryGetValue: Αυτή η μέθοδος χρησιμοποιείται για την ανάκτηση ενός αντικειμένου από τη συλλογή.
  • TryRemove: Αυτή η μέθοδος χρησιμοποιείται για την κατάργηση ενός αντικειμένου από τη συλλογή.
  • TryUpdate: Αυτή η μέθοδος χρησιμοποιείται για την ενημέρωση ενός συγκεκριμένου κλειδιού στην παρουσία ConcurrentDictionary με τη νέα τιμή που παρέχεται.

Το παρακάτω απόσπασμα κώδικα δείχνει πώς μπορείτε να δημιουργήσετε μια παρουσία ConcurrentDictionary και να προσθέσετε στοιχεία σε αυτήν:

ConcurrentDictionary obj = νέο ConcurrentDictionary ();

obj.TryAdd ("X001", "Αυτή είναι η πρώτη τιμή.");

obj.TryAdd ("X002", "Αυτή είναι η δεύτερη τιμή.");

Εάν τώρα προσπαθήσετε να προσθέσετε ένα άλλο στοιχείο αλλά με το ίδιο κλειδί, αποτυγχάνει. Ανατρέξτε στο απόσπασμα κώδικα παρακάτω.

bool success = obj.TryAdd ("X002", "Αυτή είναι η τρίτη τιμή.");

Η τιμή της μεταβλητής επιτυχίας είναι "false" καθώς αποτυγχάνει η προσπάθεια προσθήκης μιας τιμής με το ίδιο κλειδί.

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

item string = null;

bool isExist = obj.TryGetValue ("X001", στοιχείο εκτός);

Εάν επρόκειτο να ανακτήσετε όλα τα στοιχεία της συλλογής, θα μπορούσατε να χρησιμοποιήσετε το ακόλουθο απόσπασμα κώδικα.

foreach (var v σε obj)

    {

Console.WriteLine (v.Key + "---" + v.Value);

    }

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

item string = null;

bool result = obj.TryRemove ("X001", στοιχείο έξω);

Αν επρόκειτο να καταργήσετε όλα τα στοιχεία, θα μπορούσε να χρησιμοποιηθεί το ακόλουθο απόσπασμα κώδικα.

obj.Clear ();

Τώρα, εξετάστε τις ακόλουθες δύο στατικές μεθόδους.

στατικό κενό FirstTask (ConcurrentDictionary obj)

        {

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

            {

obj.TryAdd (i.ToString (), i.ToString ());

Νήμα. Sleep (100);

            }

        }

στατικό κενό SecondTask (ConcurrentDictionary obj)

        {

Νήμα. Sleep (1000);

foreach (αντικείμενο var σε obj)

            {

Console.WriteLine ("Key:" + item.Key + "Value:" + item.Value);

Νήμα. Sleep (100);

            }

        }

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

ConcurrentDictionary obj = νέο ConcurrentDictionary ();

Task firstTask = Task.Run (() => FirstTask (obj));

Task secondTask = Task.Run (() => SecondTask (obj));

δοκιμάστε

{

Task.WaitAll (firstTask, secondTask);

}

catch (AggregateException ex)

{

// Γράψτε τον δικό σας κωδικό εδώ για να χειριστείτε την εξαίρεση

}

Εάν εκτελέσετε τον παραπάνω κώδικα, δεν θα γίνει εξαίρεση, καθώς η συλλογή εδώ είναι ασφαλής για νήματα.

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