You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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在创建池时自动配置的跟踪机制实现的,手动实例化基础池不会启用该功能。

具体原理

  1. 当你直接new DefaultObjectPool<MyClass>(...)时,使用的是最基础的池实现,没有添加对象跟踪的包装逻辑。未归还的对象只会成为垃圾等待GC回收,不会主动触发Dispose方法。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 21:35:25