مشاركة عبر


نظرة عامة BlockingCollection

BlockingCollection<T> هو فئة مجموعة مؤشر الترابط الآمن والتي توفر الميزات التالية:

  • تطبيق لنمط مُنِتج-مستهلك.

  • الإضافة المتزامنة و أخذ العناصر من مؤشرات الترابط المتعددة.

  • السعة القصوى الاختيارية.

  • عمليات الإدراج والإزالة والتي تقوم بالحظر عندما تكون المجموعة فارغة أو ممتلئة.

  • عمليات الإدراج والإزالة "try" و التي لا تقوم بالحظر أو التي تقوم بالحظر لفترة محددة من الوقت.

  • تغليف أي نوع للمجموعة التي تطبق IProducerConsumerCollection<T>

  • إلغاء الرموز المميزة للإلغاء.

  • نوعان من قوائم التعداد باستخدام foreach (For Each في Visual Basic):

    1. قائمة تعداد للقراءة فقط.

    2. قائمة التعداد التي تقوم بإزالة العناصر عندما يتم تعدادها.

دعم الإحاطة و الحظر

يدعم BlockingCollection ` 1 الإحاطة و الحظر. الإحاطة تعني أنه يمكنك تعيين الحد الأقصى لسعة المجموعة. الإحاطة مهمة في وحدات سيناريو معينة لأنها تتيح لك التحكم في الحد الأقصى لحجم المجموعة في الذاكرة، وتمنع إنتاج مؤشرات الترابط من التقدم كثيراً في إستهلاك مؤشرات الترابط.

يمكن لمؤشرات الترابط المتعددة أو المهام إضافة العناصر إلى مجموعة بشكل متزامن، و إذا وصلت المجموعة إلى سعتها القصوى المحددة ، فسيمنع إنتاج مؤشرات الترابط حتى تتم إزالة عنصر. يمكن للمستهلكين المتعددين أن يزيلوا العناصر بشكل متزامن، وإذا أصبحت المجموعة فارغة، فسيتم حظر مؤشرات الترابط المستهلكة حتى يقوم المُنتج بإضافة عنصر. يمكن لإنتاج مؤشر ترابط أن يقوم باستدعاء CompleteAdding للإشارة إلى أنه لن يتم إضافة المزيد من العناصر. خاصية مراقبة المستهلكين IsCompleted لمعرفة عندما تكون المجموعة فارغة ولن يتم إضافة المزيد من العناصر. يلي مثال يبين BlockingCollection بسيطة مع سعة قراءة 100. tكـk المنتج بإضافة عناصر إلى المجموعة كـ طويلاً كـ بعض الشرط الخارجي هو صحيح، ومن ثم استدعاء CompleteAdding. مهمة مستهلك بأخذ عناصر حتى IsCompletedخاصية صحيحاً، كما هو موضح في التالية مثال:

' A bounded collection. It can hold no more 
' than 100 items at once.
Dim dataItems = New BlockingCollection(Of Data)(100)

' A simple blocking consumer with no cancellation.
Task.Factory.StartNew(Sub()
                          While dataItems.IsCompleted = False
                              Dim dataItem = dataItems.Take
                              Process(dataItem)
                          End While
                          Console.WriteLine(vbCrLf & "No more items to take.")
                      End Sub)

' A simple blocking producer with no cancellation.
Task.Factory.StartNew(Sub()
                          While moreItemsToAdd = True
                              Dim item As Data = GetData()

                              ' Blocks if numbers.Count = dataItems.BoundedCapacity
                              dataItems.Add(item)
                          End While

                          ' Let consumer know we are done.
                          dataItems.CompleteAdding()
                      End Sub)
            // A bounded collection. It can hold no more 
            // than 100 items at once.
            BlockingCollection<Data> dataItems = new BlockingCollection<Data>(100);


            // A simple blocking consumer with no cancellation.
            Task.Factory.StartNew(() => 
            {
                while (!dataItems.IsCompleted)
                {
                    // Blocks if number.Count == 0
                    Data data = dataItems.Take();
                    Process(data);
                }
                Console.WriteLine("\r\nNo more items to take.");
            });

            // A simple blocking producer with no cancellation.
            Task.Factory.StartNew(() =>
            {
                while (moreItemsToAdd)
                {
                    Data data = GetData();
                    // Blocks if numbers.Count == dataItems.BoundedCapacity
                    dataItems.Add(data);
                }
                // Let consumer know we are done.
                dataItems.CompleteAdding();
            });

لمثال كامل، راجع كيفية القيام بما يلي: إضافة و أخذ العناصر بشكل فردي من BlockingCollection.

عمليات الحظر الموقوتة

انقضاء المنع TryAdd()و TryTake()يحاول الأسلوب العمليات قراءة مجموعات، إلى إضافة أو الحصول تشغيل العنصر. إذا كان عنصراً متوفراً يتم وضعه في المتغير الذي تم تمريره بواسطة المرجع، و يقوم الأسلوب بإرجاع true. إذا لم يتم استرداد أي عنصر بعد إنقضاء فترة محددة فسيقوم الأسلوب بإرجاع false. ويكون مؤشر الترابط حراً ليقوم بعمل اخر مفيد قبل محاولة مرة أخري الوصول إلى المجموعة. للحصول على مثال لحظر الوصول المحدد زمنياً، راجع المثال الثاني في كيفية القيام بما يلي: إضافة و أخذ العناصر بشكل فردي من BlockingCollection.

عمليات إلغاء الإضافة و الأخذ

عادةً يتم تنفيذ عمليات الإضافة و الأخذ في تكرار حلقي. يمكنك إلغاء الأمر تكرار حلقي بتمرير في CancellationToken TryAdd()أو TryTake()الأسلوب، و ثم يتم الآن التدقيق من القيمة الرمز المميز الذي IsCancellationRequestedخاصية على كل تكرار. إذا كانت القيمة true، إذن فالأمر متروك لك لتقوم بالرد علي طلب الإلغاء بتنظيف أية موارد والخروج من التكرار الحلقي. يظهر المثال التالي التحميل الزائد من TryAdd()التي تأخذ رسالة بإلغاء الرمز المميز، والتعليمات البرمجية التي تستخدمها:

Do While moreItems = True
    ' Cancellation causes OCE. We know how to handle it.
    Try
        success = bc.TryAdd(itemToAdd, 2, ct)
    Catch ex As Exception
        bc.CompleteAdding()
        Exit Do
    End Try
Loop
do
{
    // Cancellation causes OCE. We know how to handle it.
    try
    {
        success = bc.TryAdd(itemToAdd, 2, ct);
    }
    catch (OperationCanceledException)
    {
        bc.CompleteAdding();
        break;
    }
    //...
} while (moreItems == true);

للحصول على مثال عن كيفية إضافة دعم الإلغاء، راجع المثال الثاني في كيفية القيام بما يلي: إضافة و أخذ العناصر بشكل فردي من BlockingCollection.

تحديد نوع المجموعة

When you إنشاء a BlockingCollection<T>, you can specify not فقط the bounded السعة but also the نوع of مجموعة إلى استخدم. على سبيل المثال، يمكنك تحديد ConcurrentConcurrentQueue لـسلوك الأول دخولاً- هو الأول خروجاً (FIFO) ، أو ConcurrentStack<T> للحصول على سلوك الأخير دخولاً- هو الأول خروجاً (LIFO). يمكن إستخدام أي فئة مجموعة تقوم بتنفيذ الواجهة IProducerConsumerCollection<T> . نوع المجموعة الافتراضي لـ BlockingCollection<T> هو ConcurrentQueue<T>. The following تعليمات برمجية مثال shows how إلى إنشاء a BlockingCollection<T> of سلاسل that has a السعة of 1000 و uses a ConcurrentBag:

Dim bc = New BlockingCollection(Of String)(New ConcurrentBag(Of String()), 1000)
BlockingCollection<string> bc = new BlockingCollection<string>(new ConcurrentBag<string>(), 1000 );

لمزيد من المعلومات، راجع كيفية القيام بما يلي: إضافة إحاطة و حظر وظيفة في فئة مجموعة.

دعم IEnumerable

يوفر BlockingCollection<T> الأسلوب GetConsumingEnumerable الذي يتيح للمستهلكين استخدامforeach ( For Each في Visual Basic) لإزالة العناصر حتى إكمال المجموعة، مما يعني أنها فارغة ولن تتم إضافة المزيد من العناصر. لمزيد من المعلومات، راجع كيفية القيام بما يلي: استخدم ForEach لإزالة عناصر في BlockingCollection.

استخدام BlockingCollections كثيرة كواحدة

بالنسبة للسيناريوهات التي يحتاجها المستهلك أن تأخذ العناصر من مجموعات متعددة في وقت واحد، يمكنك إنشاء صفائف من BlockingCollection<T> و استخدام الأساليب الثابتة مثل TakeFromAny() و AddToAny() التي ستقوم بإضافة أو الحصول على أي من المجموعات في الصفيف. إذا تم حظر مجموعة واحدة، فسيحاول الأسلوب مباشرة واحدة أخرى حتى تعثر عليها واحدة يمكنها تنفيذ العملية. لمزيد من المعلومات، راجع كيفية القيام بما يلي: استخدم صفائف من حظر مجموعات داخل خط أنابيب.

راجع أيضًا:

المرجع

System.Collections.Concurrent

موارد أخرى

مجموعات و بنيات البيانات

مجموعات مؤشر الترابط الآمن