I'm using a ConcurrentQueue<Result> to store results of a certain activity that occurs in my system (ASP.NET Core 6). It works well.
But now I have a new requirement: I need a Result.Id property - a long value, similar to a sequential database primary key. When I enqueue an item, it must get the next value in the sequence, i.e. queue.Count + 1.
When I enqueue items, I don't use locks because ConcurrentQueue does that for me. But now that need Id, I must:
- lock access to
Enqueue() - determine the queue's size
- increment by one
- set the item's
Id - enqueue the item
or:
- lock access to
Enqueue() - enqueue the item
- determine the queue's new size
- update the item's
Id(but it will be in an inconsistent state until then)
Can I do this without locking the Enqueue() method? Or maybe there's a better way? (Though I prefer to continue using ConcurrentQueue, if possible, as it already works well for what I have.)
Instead of assigning the Id when adding the items, you can assign it after you have finished adding items to the queue. You can use a
Selectwith index, e.g.:This leads to the following output:
Depending on the size of the queue and the number of times you iterate it, you can also add a
ToArrayafter theSelectin order to avoid assigning the Ids multiple times.Important to note that this only works if you can clearly separate the phase of adding items to the queue and processing the queue.