Description
Memory leak caused by AsyncLocal<> from PerLogicalCallContextScopeManager
Hi,
Many thanks for this project. We've used it for web for years, it works fine.
But recently we've adopted the implementation into a Windows service. Got bit of problem.
Bit explanation on background:
Our service is driven/triggered by a message bus. When message comes in, it creates a new Task. And this task runs a long-running job.
Also, there're timers to trigger scheduled jobs.
Each job was suppose to be wrapped within it's own scope.
Our need sounds very simple. There's a root scope, it creates all children scopes. Each child scope used for one job. Jobs may run parallel. The job is ran through Task.
The problem is the ScopeManager. Currently there're 2 types of ScopeManager (PerThreadScopeManager & PerLogicalCallContextScopeManager), but neither fit our needs.
Obviously the PerThreadScopeManager not work in this case.
So we tried PerLogicalCallContextScopeManager. But due to performance consideration, we uses .ConfigureAwait(false) everywhere (in the backend service). It causes quite bad memory leak, as the context switches, the ExecutionContext shadow-clones its' Dictionary<IAsyncLocal, object>. Ends up there're many Sope been disposed but not cleaned by GC, due to reference to the Dictionary<IAsyncLocal, object>s.
So I've added a new implementation of ScopeManager #449 , that can pass on the parent/scope relationship as non-static way. It seems there's no way to approach it with 'clean' and 'nice' code. Trouble is that current Scope and ServiceContainer design assumes the ScopeManger.CurrentScope always used by the thread. So my solution looks bit complex.
I'm not sure if there's better way to do this?