BlockingCollection Genel Bakışı
BlockingCollection<T> , aşağıdaki özellikleri sağlayan iş parçacığı açısından güvenli bir koleksiyon sınıfıdır:
Üretici-Tüketici deseninin bir uygulaması.
Birden çok iş parçacığından eşzamanlı öğe ekleme ve alma.
İsteğe bağlı maksimum kapasite.
Koleksiyon boş veya dolu olduğunda engelleyen ekleme ve kaldırma işlemleri.
Ekleme ve kaldırma işlemi, engellemeyen veya belirli bir süreye kadar engelleyen "deneme" işlemleridir.
Uygulayan tüm koleksiyon türlerini kapsüller IProducerConsumerCollection<T>
İptal belirteçleriyle iptal etme.
ile iki tür numaralandırma
foreach
(For Each
Visual Basic'te):Salt okunur numaralandırma.
Öğeleri numaralandırıldıkları gibi kaldıran numaralandırma.
Sınırlayıcı ve Engelleme Desteği
BlockingCollection<T> sınırlayıcı ve engellemeyi destekler. Sınırlayıcı, koleksiyonun maksimum kapasitesini ayarlayabileceğiniz anlamına gelir. Sınırlama, bellekteki koleksiyonun en büyük boyutunu denetlemenize olanak sağladığından ve üreten iş parçacıklarının tüketen iş parçacıklarının çok ilerisine geçmesini önlediğinden, belirli senaryolarda önemlidir.
Birden çok iş parçacığı veya görev aynı anda koleksiyona öğe ekleyebilir ve koleksiyon belirtilen maksimum kapasiteye ulaşırsa, öğe kaldırılana kadar oluşturan iş parçacıkları engellenir. Birden çok tüketici öğeleri eşzamanlı olarak kaldırabilir ve koleksiyon boşsa, bir üretici öğe ekleyene kadar tüketen iş parçacıkları engellenir. Üreten bir iş parçacığı, başka öğe eklenmeyeceklerini belirtmek için çağırabilir CompleteAdding . Tüketiciler, koleksiyonun IsCompleted ne zaman boş olduğunu ve başka öğe eklenmeyeceklerini bilmek için özelliğini izler. Aşağıdaki örnekte sınırlanmış kapasitesi 100 olan basit bir BlockingCollection gösterilmektedir. Bir üretici görevi, bazı dış koşullar true olduğu sürece koleksiyona öğe ekler ve ardından öğesini çağırır CompleteAdding. Tüketici görevi, özellik doğru olana kadar IsCompleted öğeleri alır.
// 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.Run(() =>
{
while (!dataItems.IsCompleted)
{
Data data = null;
// Blocks if dataItems.Count == 0.
// IOE means that Take() was called on a completed collection.
// Some other thread can call CompleteAdding after we pass the
// IsCompleted check but before we call Take.
// In this example, we can simply catch the exception since the
// loop will break on the next iteration.
try
{
data = dataItems.Take();
}
catch (InvalidOperationException) { }
if (data != null)
{
Process(data);
}
}
Console.WriteLine("\r\nNo more items to take.");
});
// A simple blocking producer with no cancellation.
Task.Run(() =>
{
while (moreItemsToAdd)
{
Data data = GetData();
// Blocks if numbers.Count == dataItems.BoundedCapacity
dataItems.Add(data);
}
// Let consumer know we are done.
dataItems.CompleteAdding();
});
' 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 As Data = Nothing
Try
dataItem = dataItems.Take()
Catch e As InvalidOperationException
' IOE means that Take() was called on a completed collection.
' In this example, we can simply catch the exception since the
' loop will break on the next iteration.
End Try
If (dataItem IsNot Nothing) Then
Process(dataItem)
End If
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 dataItems.Count = dataItems.BoundedCapacity.
dataItems.Add(item)
End While
' Let consumer know we are done.
dataItems.CompleteAdding()
End Sub)
Tam bir örnek için bkz . Nasıl yapılır: Bir BlockingCollection'dan Öğeleri Ayrı Ayrı Ekleme ve Alma.
Zamanlanmış Engelleme İşlemleri
Zamanlanmış engelleme TryAdd ve TryTake sınırlanmış koleksiyonlardaki işlemlerde yöntemi bir öğe eklemeye veya almaya çalışır. Bir öğe kullanılabilirse, başvuruyla geçirilen değişkene yerleştirilir ve yöntem true döndürür. Belirtilen zaman aşımı süresinden sonra hiçbir öğe alınmazsa yöntem false döndürür. Daha sonra iş parçacığı, koleksiyona yeniden erişmeye çalışmadan önce başka yararlı işler de yapabilir. Zamanlanmış engelleme erişimi örneği için, Nasıl yapılır: Bir BlockingCollection'dan Öğeleri Tek Tek Ekleme ve Alma makalesindeki ikinci örnağa bakın.
Ekleme ve Alma İşlemlerini İptal Etme
Ekleme ve Alma işlemleri genellikle döngü içinde gerçekleştirilir. veya TryTake yöntemine TryAdd bir geçirip her yinelemede CancellationToken belirtecin IsCancellationRequested özelliğinin değerini denetleyerek bir döngü iptal edebilirsiniz. Değer true ise, tüm kaynakları temizleyip döngüden çıkararak iptal isteğine yanıt vermek size bağlı olur. Aşağıdaki örnekte, iptal belirtecini TryAdd alan bir aşırı yükleme ve bunu kullanan kod gösterilmektedir:
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);
Do While moreItems = True
' Cancellation causes OCE. We know how to handle it.
Try
success = bc.TryAdd(itemToAdd, 2, ct)
Catch ex As OperationCanceledException
bc.CompleteAdding()
Exit Do
End Try
Loop
İptal desteği ekleme örneği için Bkz . Nasıl yapılır: Bir BlockingCollection'dan Öğeleri Ayrı Ayrı Ekleme ve Alma.
Koleksiyon Türünü Belirtme
Oluşturduğunuzda BlockingCollection<T>, yalnızca sınırlanmış kapasiteyi değil, aynı zamanda kullanılacak koleksiyonun türünü de belirtebilirsiniz. Örneğin, ilk ilk çıkış (FIFO) davranışı için veya ConcurrentStack<T> son ilk çıkış (LIFO) davranışı için bir belirtebilirsinizConcurrentQueue<T>. Arabirimini uygulayan herhangi bir koleksiyon sınıfını IProducerConsumerCollection<T> kullanabilirsiniz. için BlockingCollection<T> varsayılan koleksiyon türü şeklindedir ConcurrentQueue<T>. Aşağıdaki kod örneği, 1000 kapasiteye sahip ve ConcurrentBag<T>kullanan dizelerin nasıl oluşturulacağını BlockingCollection<T> gösterir:
Dim bc = New BlockingCollection(Of String)(New ConcurrentBag(Of String()), 1000)
BlockingCollection<string> bc = new BlockingCollection<string>(new ConcurrentBag<string>(), 1000 );
Daha fazla bilgi için bkz . Nasıl yapılır: Bir Koleksiyona Sınırlayıcı ve Engelleme İşlevselliği Ekleme.
IEnumerable Desteği
BlockingCollection<T>, tüketicilerin koleksiyon tamamlanana kadar öğeleri kaldırmak için (For Each
Visual Basic'te) kullanmasına foreach
olanak tanıyan bir GetConsumingEnumerable yöntem sağlar; bu da boş olduğu ve başka öğe eklenmeyecek olduğu anlamına gelir. Daha fazla bilgi için bkz . How to: Use ForEach to Remove Items in a BlockingCollection.
Birçok BlockingCollections'i Tek Olarak Kullanma
Tüketicinin aynı anda birden çok koleksiyondan öğe alması gereken senaryolar için dizileri BlockingCollection<T> oluşturabilir ve dizideki koleksiyonlardan herhangi birine eklenecek veya bu koleksiyonlardan alacak ve AddToAny gibi TakeFromAny statik yöntemleri kullanabilirsiniz. Bir koleksiyon engelleniyorsa, yöntemi işlemi gerçekleştirebilecek bir koleksiyon bulana kadar hemen başka bir koleksiyon dener. Daha fazla bilgi için bkz . How to: Use Arrays of Blocking Collections in a Pipeline.
Ayrıca bkz.
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin