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

使用AWS C# SDK操作DigitalOcean获取对象列表触发ObjectDisposedException

解决AmazonS3Client调用ListObjects时触发的ObjectDisposedException异常

我之前也碰到过一模一样的问题!当调用ListObjects方法获取存储桶对象列表时,突然抛出了System.ObjectDisposedException,提示无法访问已释放的对象。先贴一下和你几乎一致的问题代码:

private string S3_ACCESS_KEY = "blablabla";
private string S3_SECRET_KEY = "blablabla";
private string S3_HOST_ENDPOINT = "https://fra1.digitaloceanspaces.com";
private string S3_BUCKET_NAME = "launchers";
private AmazonS3Client _client;

public DO() {
    AmazonS3Config config = new AmazonS3Config();
    config.ServiceURL = S3_HOST_ENDPOINT;
    _client = new AmazonS3Client(S3_ACCESS_KEY, S3_SECRET_KEY, config);
}

public List<string> ListObject() {
    var objects = _client.ListObjects(S3_BUCKET_NAME); // 抛出System.ObjectDisposedException异常
    var objectsList = objects.S3Objects.Select(c => c.Key).ToList();
    return objectsList;
}

核心原因

这个异常的本质是你的AmazonS3Client实例_client在调用ListObjects之前已经被释放了。常见触发场景包括:

  • 其他代码中手动调用了_client.Dispose()
  • 如果DO类实现了IDisposable接口,且在Dispose方法中释放了_client,当DO实例被销毁时会连带释放客户端
  • 异步环境下的线程安全问题,导致客户端被意外回收
  • 客户端实例被GC提前回收(虽然这种情况少见,但确实可能发生)

解决方案

1. 每次调用时创建并管理客户端生命周期

如果你的ListObject方法不是高频调用,最稳妥的方式是在方法内部创建客户端,用using语句自动管理释放:

public List<string> ListObject() {
    using var config = new AmazonS3Config { ServiceURL = S3_HOST_ENDPOINT };
    using var client = new AmazonS3Client(S3_ACCESS_KEY, S3_SECRET_KEY, config);
    var objects = client.ListObjects(S3_BUCKET_NAME);
    return objects.S3Objects.Select(c => c.Key).ToList();
}

这样每次调用都会生成全新的客户端实例,用完自动释放,从根源上避免生命周期冲突。

2. 排查意外释放客户端的代码

全局搜索项目,检查是否存在以下情况:

  • 手动调用_client.Dispose()的代码
  • 将DO实例放在using块中使用(如果DO实现了IDisposable)
  • 其他线程中对_client的不当操作

3. 改用异步API(推荐)

Amazon SDK官方更推荐使用异步方法,同步API存在一些隐藏的资源管理问题。改成异步版本:

public async Task<List<string>> ListObjectAsync() {
    using var config = new AmazonS3Config { ServiceURL = S3_HOST_ENDPOINT };
    using var client = new AmazonS3Client(S3_ACCESS_KEY, S3_SECRET_KEY, config);
    var objects = await client.ListObjectsAsync(S3_BUCKET_NAME);
    return objects.S3Objects.Select(c => c.Key).ToList();
}

异步API不仅性能更优,还能减少同步场景下的资源竞争问题。

4. 依赖注入管理客户端(适用于框架项目)

如果是ASP.NET Core这类框架项目,推荐通过依赖注入让框架管理客户端生命周期:

// 在Program.cs中注册服务
builder.Services.AddAWSService<IAmazonS3>(new AmazonS3Config { 
    ServiceURL = S3_HOST_ENDPOINT 
});

然后在DO类中注入客户端:

private readonly IAmazonS3 _client;

public DO(IAmazonS3 client) {
    _client = client;
}

框架会自动处理客户端的创建、复用和释放,彻底避免Disposed异常。

内容的提问来源于stack exchange,提问作者God Of Penguins

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:14:47