AsyncLocal <>中的明显内存泄漏

时间:2019-09-22 14:43:24

标签: c# asynchronous garbage-collection

我有一个庞大的CI构建测试套件,超过3,000个测试。为了并行运行测试,我大量使用了AsyncLocal<T>对象。麻烦的是,自从我开始这样做以来,CI构建机器人已完成了大约75%,然后由于内存不足而炸裂了。除了新引入的AsyncLocal<T>对象(用于存储从布尔值到复杂对象的任何东西)之外,没有其他罪魁祸首。

我想我正在以某种方式滥用系统,并且有一种使用“ AsyncLocal<T>”的“适当”方法,以便一旦当前上下文终止,其值就会被垃圾回收。

在我发现AsyncLocal<T>存在之前,我试图自己使用自己的名为Parallelizable<T>的类来实现此功能可能会有所帮助。可以使用NUnit的TestExecutionContext.CurrentContext.CurrentTest.FullName来实现,但是它的速度很慢,所以我深入研究了底层代码,发现它正在使用AsyncLocal<>,所以我决定削减实现并更改{{1} }作为Parallelizable<T>的包装,这样我就可以对现有测试进行最小程度的暴力测试。那是我开始摆脱内存故障的时候。

什么是确保这些值经过GC处理的正确方法?

这是我AsyncLocal<T>的代码,FWIW:

Parallelizable<T>

更新:我通过在测试夹具基类中找到了使用 public class Parallelizable<T> { private readonly AsyncLocal<T> _asyncLocal = new AsyncLocal<T>(); private readonly AsyncLocal<bool> _valueSet = new AsyncLocal<bool>(); private readonly T _defaultValue; private readonly Func<T> _defaultFunc; public Parallelizable() { _valueSet.Value = false; } public Parallelizable(T defaultValue) { _defaultValue = defaultValue; } public Parallelizable(Func<T> defaultFunc) { _defaultFunc = defaultFunc; } public T Value { get { if (!_valueSet.Value) { _asyncLocal.Value = _defaultFunc != null ? _defaultFunc.Invoke() : _defaultValue; _valueSet.Value = true; } return _asyncLocal.Value; } set { _asyncLocal.Value = value; _valueSet.Value = true; } } } 和大型对象的密集位置,并在{{1} }方法确保将AsyncLocal<>属性的值设置为TearDown()。这解决了我的问题。

但是,问题仍然悬而未决:为什么AsyncLocal对象本身被GC'd了,它们的所有值也都未被GC'd了?这似乎是null实现中的错误,不是吗?

0 个答案:

没有答案