Conversation
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @dotnet/area-system-collections |
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
b9306af to
aa19a9e
Compare
aa19a9e to
e773a14
Compare
gfoidl
left a comment
There was a problem hiding this comment.
Is there a test that repro the issue?
If not, so please add one.
The fix itself LGTM.
Yes. I added a regression test in It covers the scenario from the issue: an item remains in the collection after a consumer operation is canceled, so The test then removes the remaining item and verifies that |
|
Just a quick follow-up on this PR. I’d appreciate any feedback when you get a chance. Thanks! |
Description
BlockingCollection.IsCompletedcurrently uses_occupiedNodes.CurrentCountto determine whether the collection is empty.However,
_occupiedNodesis also used to synchronize consumer operations. This can causeIsCompletedto temporarily reporttrueeven though the collection still contains an item.For example:
BlockingCollectioncontains a single item.CompleteAdding()is called, soIsCompletedis initiallyfalse.Takeoperation and successfully waits on_occupiedNodes._occupiedNodes.CurrentCountbecomes0, causingIsCompletedto returntrueeven though the item has not yet been removed from the collection._occupiedNodes.CurrentCountis restored to1.IsCompletedthen returns tofalse.As a result,
IsCompletedcan transition fromfalsetotrueand back tofalseeven though the item was never removed from the collection.Fix
Introduce a separate
_actualCountfield to track the number of items successfully added to and removed from the collection._actualCountis initialized from the existing collection count and updated atomically after each successful add or remove operation, specifically inTryAddWithNoTimeValidationandTryTakeWithNoTimeValidation.CountandIsCompletednow use_actualCountinstead of_occupiedNodes.CurrentCount.This separates the synchronization state of
_occupiedNodesfrom the actual item count and prevents consumer cancellation from changing the state reported byIsCompleted.Tests
Added a regression test that verifies that
IsCompletedremainsfalsewhen:CompleteAdding()has been called,The test then removes the remaining item and verifies that
IsCompletedbecomestrue.Closes #109217