You're basically correct in your assessment.
A queue is a simple FIFO type queue. Whereas the ConcurrentQueue is threadsafe (Meaning that you can have multiple threads trying to read/write onto the queue at once).
A blocking collection is essentially a wrapper around a ConcurrentQueue (So it's also threadsafe), but the big difference is that it will limit the capacity and wait.
Let's take an example :
BlockingCollection<int> blockingCollection = new BlockingCollection<int>(2);
blockingCollection.Add(1);
blockingCollection.Add(2);
blockingCollection.Add(3); <-- Execution stops and waits here
If we ran this with a debugger, we would see that we could step through the code until we tried to add the number 3, and then everything would freeze. Why? Because we intitialized our BlockingCollection with an initial size of 2. Meaning it can only hold 2 items.
If we hit this limit, and try to add more, our thread will essentially wait until there is space to add more messages. In this way, we can limit the queue size spiraling out of control.
I will say that the BlockingCollection is not that popular anymore due to the fact it actually blocks (and holds) the thread while waiting. A more popular solution is Channels in C# which are non blocking due to the async/await nature of the queue https://dotnetcoretutorials.com/2020/11/24/using-channels-in-net-core-part-1-getting-started/