Boost Your .NET Projects with Spargine: Maximize Thread-Safe Performance in .NET with DistinctBlockingCollection

Spargine is a collection of open-source assemblies and NuGet packages designed for .NET 10, which I have been developing and maintaining since the release of .NET Framework 2. These assemblies are not only a core part of my projects but are also actively deployed in production environments across several companies I collaborate with.

Get Spargine

You can access the source code and NuGet packages here:

Introduction

In high-performance .NET applications, especially those involving producer-consumer patterns, thread-safe collections are essential. One of the most commonly used types is BlockingCollection<T>, which provides a thread-safe way to add and remove items while automatically handling thread blocking when the collection is full or empty.

But what if you also need to ensure no duplicate items are ever added to the collection?

That’s where DistinctBlockingCollection<T>, part of the Spargine library, comes in.

Why BlockingCollection Matters

BlockingCollection<T> wraps an IProducerConsumerCollection<T> (like ConcurrentQueue<T>) to simplify multi-threaded coordination. It’s ideal for:

  • Managing producer-consumer queues.
  • Avoiding race conditions and busy waiting.
  • Providing blocking behavior when adding/removing items.

However, it does not prevent duplicates, which can be problematic in scenarios like task processing queues, caching layers, or real-time messaging systems.

Introducing DistinctBlockingCollection<T>

DistinctBlockingCollection<T> extends the capabilities of BlockingCollection<T> by adding duplicate filtering — ensuring each item in the collection is unique.

Key Features

Constructors

  • DistinctBlockingCollection()
    Creates a new instance with default settings.
  • DistinctBlockingCollection(IEnumerable<T> collection)
    Initializes the collection and loads unique items from the provided sequence.
  • DistinctBlockingCollection(int boundedCapacity)
    Sets a maximum size to prevent memory overuse and throttle producers.

Methods

  • Add(T item, CancellationToken cancellationToken)
    Adds an item if it doesn’t already exist. Throws an exception if a duplicate is detected.
  • AddRange(IEnumerable<T> items, CancellationToken cancellationToken)
    Adds multiple items to the DistinctBlockingCollection, skipping duplicates.
  • Clear()
    Removes all items, effectively resetting the collection.
  • Clone()
    Returns a deep copy of the current collection.
  • Contains(T item)
    Checks if the item is already present.
  • ContainsAny(IEnumerable<T> items)
    Determines whether it contains any of the specified items.
  • ContainsAny(IEnumerable<T> items)
    Determines whether the DistinctBlockingCollection contains any of the specified items.
  • Remove(T item)
    Removes an item.
  • TryAdd(…) (Multiple Overloads)
    Attempts to add an item with optional timeout and cancellation support. Returns false if the item is a duplicate or the operation times out.
  • TryAddRange(IEnumerable<T> items, int millisecondsTimeout, CancellationToken cancellationToken = default)
    Attempts to add multiple items to the list without blocking, skipping duplicates.

Property

  • IsReadOnly
    Indicates whether the collection is accepting new items.

When to Use DistinctBlockingCollection<T>

Use this collection in scenarios where:

  • Duplicate processing would cause errors or inefficiencies.
  • You need guaranteed uniqueness in a producer-consumer queue.
  • You want an easy upgrade BlockingCollection<T> without major code changes.

Summary

If you’re working with multi-threaded workflows and need to prevent duplicate data, DistinctBlockingCollection<T> is a simple yet powerful enhancement. Built on top of proven .NET concurrency patterns, it combines the robustness of BlockingCollection<T> with an extra layer of control — all without sacrificing performance.

Get Involved!

The success of open-source projects like Spargine relies on community contributions. If you find these updates useful or have ideas for further improvements, I encourage you to contribute by:

  • Submitting pull requests
  • Reporting issues
  • Suggesting new features

Your input is invaluable in making Spargine an even more powerful tool for the .NET community.

If you are interested in contributing or have any questions, feel free to contact me via email at dotnetdave@live.com. Your support and collaboration are greatly appreciated!

Thank you, and happy coding!

Pick up any books by David McCarter by going to Amazon.com: http://bit.ly/RockYourCodeBooks

One-Time
Monthly
Yearly

Make a one-time donation

Make a monthly donation

Make a yearly donation

Choose an amount

$5.00
$15.00
$100.00
$5.00
$15.00
$100.00
$5.00
$15.00
$100.00

Or enter a custom amount

$

Your contribution is appreciated.

Your contribution is appreciated.

Your contribution is appreciated.

DonateDonate monthlyDonate yearly

If you liked this article, please buy David a cup of Coffee by going here: https://www.buymeacoffee.com/dotnetdave

© The information in this article is copywritten and cannot be preproduced in any way without express permission from David McCarter.


Discover more from dotNetTips.com

Subscribe to get the latest posts sent to your email.

3 thoughts on “Boost Your .NET Projects with Spargine: Maximize Thread-Safe Performance in .NET with DistinctBlockingCollection

  1. Looking at the code it doesn’t look like it prevents duplicates in the case of multiple threads adding items. The call to IsNotInCollection and Add are not done atomically – another thread could add the same item between IsNotInCollection returning and Add being called.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.