-
Couldn't load subscription status.
- Fork 5.2k
Description
Description
After upgrading to System.Threading.Tasks.Dataflow 8.0.0 from 4.11.1 I started noticing memory leaks originated on hosted services that implement a producer/consumer pattern using BufferBlock. After a closer look at a couple of process dumps, I could see lots of callback registrations on cancellation tokens presumably from DataflowBlock.OutputAvailableAsync:
I've checked the source code of DataflowBlock.OutputAvailableAsync and found that, since version 8.0.0, the registration to the CancellationToken provided to OutputAvailableAsync is no longer disposed. Actually, the delegate s_handleCompletion, which was used in earlier versions for that purpose, is never invoked. I guess that this misbehaviour, together with my implementation, that uses long-lived cancellation tokens to read from the BufferBlock, is what causes that memory leak.
Reproduction Steps
Given a hosted service implementing producer/consumer pattern using a BufferBlock, using always the same CancellationTokenSource to provide the CancellationToken to OutputAvailableAsync, then, just feed the consumer. The more items are produced, the faster the memory leak will show up.
Expected behavior
No memory leak.
Actual behavior
Memory leak
Regression?
I did not notice that behaviour in System.Threading.Tasks.Dataflow 4.11.1
Known Workarounds
In my case, switching from BufferBlock<T> to Channel<T>, which is not affected by this issue, was my "workaround".
Configuration
No response
Other information
No response
