DefaultObjectPool未释放未归还IDisposable对象?求技术解答
问题:未归还的池对象未自动释放的原因?
根据官方文档说明,当使用**DefaultObjectPoolProvider**且泛型类型T实现IDisposable接口时,未归还至对象池的实例会被自动释放。但编写测试程序验证后,发现未归还的对象并未被释放,请问原因是什么?
示例测试代码
using System; using Microsoft.Extensions.ObjectPool; namespace ConsoleApp9 { internal class Program { private static void Main(string[] args) { Console.WriteLine("Started"); using var a1 = new MyClass("a1"); using var b1 = new MyClass("b1"); var pool = new DefaultObjectPool<MyClass>(new DefaultPooledObjectPolicy<MyClass>()); var a = pool.Get(); var b = pool.Get(); //pool.Return(a); //pool.Return(b); Console.WriteLine("Finished"); } } public class MyClass : IDisposable { public MyClass() { } public MyClass(string id) { Id = id; } public void Dispose() { Console.WriteLine($"Disposing MyClass.Id={Id}"); } public string Id { get; } = Guid.NewGuid().ToString(); } }
测试输出结果
Started Finished Disposing MyClass.Id=b1 Disposing MyClass.Id=a1
原因分析与解决方案
核心问题
你直接手动实例化了DefaultObjectPool,而非通过DefaultObjectPoolProvider创建对象池——官方文档中提到的未归还对象自动释放逻辑,是由DefaultObjectPoolProvider在创建池时自动配置的跟踪机制实现的,手动实例化基础池不会启用该功能。
具体原理
- 当你直接
new DefaultObjectPool<MyClass>(...)时,使用的是最基础的池实现,没有添加对象跟踪的包装逻辑。未归还的对象只会成为垃圾等待GC回收,不会主动触发Dispose方法。 DefaultObjectPoolProvider会自动识别泛型类型是否实现IDisposable,如果是,会为池添加DisposableTrackingPooledPolicy包装。这个包装类会跟踪所有从池中取出的对象,当对象被GC回收且未被归还时,自动调用其Dispose方法。
修正后的代码
using System; using Microsoft.Extensions.ObjectPool; namespace ConsoleApp9 { internal class Program { private static void Main(string[] args) { Console.WriteLine("Started"); using var a1 = new MyClass("a1"); using var b1 = new MyClass("b1"); // 通过DefaultObjectPoolProvider创建池,自动启用IDisposable跟踪 var provider = new DefaultObjectPoolProvider(); var pool = provider.Create<MyClass>(); var a = pool.Get(); var b = pool.Get(); // 不调用Return,验证自动释放 //pool.Return(a); //pool.Return(b); Console.WriteLine("Finished"); } } public class MyClass : IDisposable { public MyClass() { } public MyClass(string id) { Id = id; } public void Dispose() { Console.WriteLine($"Disposing MyClass.Id={Id}"); } public string Id { get; } = Guid.NewGuid().ToString(); } }
修正后预期输出
运行修正代码后,未归还的池对象会被自动释放,输出类似:
Started Finished Disposing MyClass.Id=b1 Disposing MyClass.Id=a1 Disposing MyClass.Id=xxx(池对象a的ID) Disposing MyClass.Id=yyy(池对象b的ID)
内容的提问来源于stack exchange,提问作者Timur Lemeshko
相关产品推荐
相关产品推荐

