עבודה עם אוספי חוטים בטוחים: ConcurrentStack ו- ConcurrentQueue

אוספי כספות חוטים הוצגו לראשונה ב- .Net 4 עם הכנסת מרחב השמות System.Collections.Concurrent. סוגי האוספים במרחב השמות System.Collections.Concurrent מכילים אוסף של שיעורי איסוף בטוחים בשרשור.

ConcurrentStack

מחסנית היא מבנה נתונים שעובד על בסיס LIFO (האחרון בכניסה הראשונה). מחלקת ConcurrentStack היא מקבילה בטוחה לשרשור של מחלקת ה- Stack הכללית. ConcurrentStack הוא מחלקת אוספים גנרית בטוחה, שהוצגה לראשונה במסגרת .Net Framework 4. להלן רשימת השיטות החשובות במחלקה זו המדגימות את הפעולות האפשריות.

  1. Push (אלמנט T) - משתמשים בשיטה זו להוספת נתונים מסוג T.
  2. PushRange - ניתן להשתמש בשיטה זו כדי להוסיף מערך של פריטים מסוג T.
  3. TryPop (out T) - שיטה זו משמשת לאחזור האלמנט הראשון מהערימה. זה מחזיר אמת בהצלחה, אחרת לא נכון.
  4. TryPeek (מחוץ T) - שיטה זו משמשת לאחזור האלמנט הבא מהערימה אך היא אינה מסירה את האלמנט מהערימה. שים לב שבדומה לשיטת TryPop (out T), היא מחזירה נכון בהצלחה ושקר אחרת.
  5. TryPopRange - שיטה זו עמוסה יתר על המידה ועובדת בדומה ל- TryPop אך משמשת להחזרת מערכים מהערימה

כך תוכל ליצור מופע של מחלקת ConcurrentStack ולדחוף אליו נתונים.

ConcurrentStack concurrentStack = new ConcurrentStack();

for (Int32 index = 0; index < 10; index++)

{

       concurrentStack.Push(index);

}

כדי לשלוף את האלמנטים מתוך ערימה מקבילה, תוכל למנף את שיטת TryPop (out T) כפי שמוצג להלן.

Int32 data;

bool success = concurrentStack.TryPop(out data);

רישום הקוד הבא ממחיש כיצד ניתן לאחסן ולאחזר נתונים אל מחסנית בו זמנית וממנה.

static void Main(string[] args)

       {

           ConcurrentStack concurrentStack = new ConcurrentStack();

           for (Int32 index = 0; index < 100; index++)

           {

               concurrentStack.Push(index);

           }

           while (concurrentStack.Count > 0)

           {

               Int32 data;

               bool success = concurrentStack.TryPop(out data);

               if (success)

              {

                   Console.WriteLine(data);

               }

           }

           Console.Read();

       }

בעת ביצוע רישום הקוד לעיל, המספרים 0 עד 99 יוצגו בסדר הפוך בחלון המסוף.

ConcurrentQueue

תור הוא מבנה נתונים שעובד על בסיס FIFO (ראשון בכניסה ראשונה). הכיתה ConcurrentQueue ב- .Net משמשת כתור גנרי מבוסס FIFO מבוסס חוט.

להלן רשימת השיטות החשובות בשיעור ConcurrentQueue.

  1. Enqueue (אלמנט T) - משתמשים בשיטה זו להוספת פריט מסוג T לתור
  2. TryPeek (מחוץ T) - משתמשים בשיטה זו כדי לאחזר את האלמנט הבא מהתור אך הוא אינו מסיר את האלמנט מהתור. שיטה זו מחזירה נכונה בהצלחה ושגויה כאשר היא נכשלת.
  3. TryDequeue (out T) - שיטה זו משמשת לאחזור האלמנט הראשון מהתור. בניגוד לשיטת TryPeek (out T), הוא מסיר את האלמנט מהתור. שיטה זו מחזירה נכונה על הצלחה ושקר אחרת.

קטע הקוד הבא מראה כיצד ניתן ליצור מופע של המחלקה ConcurrentQueue לאחסון מספרים שלמים.

ConcurrentQueue concurrentQueue = new ConcurrentQueue();

כדי לאחסן אלמנטים למופע התור במקביל תוכלו לנצל את שיטת Enqueue כמוצג להלן.

concurrentQueue.Enqueue(100);

רישום הקוד הבא ממחיש כיצד ניתן לאחסן ולשלוף אלמנטים לתור במקביל.

ConcurrentQueue concurrentQueue = new ConcurrentQueue();

for (int index = 0; index < 100; index++)

{

     concurrentQueue.Enqueue(index);

}

Int32 item;

while (concurrentQueue.TryDequeue(out item))

{

     Console.WriteLine(item);

}

כאשר אתה מבצע את רישום הקוד לעיל, המספרים 0 עד 99 יוצגו בחלון המסוף.

שים לב ששני המחלקות ConcurrentStack ו- ConcurrentQueue הן בטיחות אשכולות והן יכולות לנהל בעיות נעילה וסנכרון באופן פנימי.

ניתן גם להמיר את מופע התור במקביל למערך על ידי ביצוע שיחה לשיטת ToArray (). קטע הקוד הבא ממחיש כיצד ניתן להשיג זאת.

ConcurrentQueue concurrentQueue = new ConcurrentQueue();

for (Int32 index = 0; index < 100; index++ )

   concurrentQueue.Enqueue(index);

Int32[] integerArray = concurrentQueue.ToArray();

foreach (int i in integerArray)

{

   Console.WriteLine(i);

}

המאפיין IsEmpty של המחלקה ConcurrentQueue מחזיר true הוא האוסף ריק, כוזב אחרת. קטע הקוד הבא מראה כיצד ניתן להשתמש בשיטה זו.

ConcurrentQueue concurrentQueue = new ConcurrentQueue();

for (Int32 index = 0; index < 100; index++ )

concurrentQueue.Enqueue(index);

while(!concurrentQueue.IsEmpty)

{

     Int32 result;

     concurrentQueue.TryDequeue(out result);

     Console.WriteLine(result);

}