繁体   English   中英

多次运行功能时无法访问已处置的对象

[英]Cannot access a disposed object when running function more than once

我有一个ASP.NET Core 2.1应用程序,但出现错误:

无法访问已处置的对象。 对象名称:“ Amazon.S3.AmazonS3Client”

尝试调用我的AWS S3读取对象服务时。 该服务第一次运行,第二次及以后失败。

我在startup.cs中具有以下内容:

services.AddSingleton<IAWSService, AWSService>();
services.AddAWSService<IAmazonS3>();

(我尝试将AsScoped()配置为无效。)

这是引起问题的功能:

public class AWSService : IAWSService
{
    private readonly IAmazonS3 _s3Client;

    public AWSService(IAmazonS3 s3Client)
    {
        _s3Client = s3Client;
    }

    public async Task<byte[]> ReadObjectFromS3Async(string bucketName, string keyName)
    {
        try
        {
            GetObjectRequest request = new GetObjectRequest
            {
                BucketName = bucketName,
                Key = keyName
            };

            using (_s3Client)
            {
                MemoryStream ms = new MemoryStream();

                using (var getObjectResponse = await _s3Client.GetObjectAsync(request))
                {
                    getObjectResponse.ResponseStream.CopyTo(ms);
                }
                var download = new FileContentResult(ms.ToArray(), "application/pdf");

                return download.FileContents;
            }

        }
        catch (AmazonS3Exception e)
        {
            Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message);
        }
        catch (Exception e)
        {
            Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
        }
        return null;

    }
}

}

我第一次运行该函数时,一个断点显示this.s3client没有被处理,但是随后尝试运行此函数表明s3client被处理了,因此出现了错误。

更新资料

我从控制器调用此函数:

public class CorrespondenceItemController : Controller
{
    private IAWSService _awsService;

    public CorrespondenceItemController(IAWSService aWSService)
    {
        _awsService = aWSService;
    }

    public async Task<ActionResult<dynamic>> Send([FromBody]CorrespondenceItemSendViewModel model)
    {

        var attachment = await _awsService.ReadObjectFromS3Async(bucket, key)
    }
}

这是因为您将_s3Client的用法包装在using块中,该块随后将处理该实例。

不要那样做

通过不显式或隐式处理_s3Client ,让IoC容器为您处理_s3Client

鉴于对Amazon .NET AWS SDK的AmazonS3线程安全吗?的答案,可以将包装器注册为单例 是是的”。 这意味着您的应用程序在任何给定时间都有一个AWSService实例,并且该类将对所有请求使用相同的IAmazonS3实例。

然后,您只需要在应用程序生命周期结束时进行处理,您的IoC容器就可以处理它。

使用是调用dispose的try / finally块的简写。

using (_s3Client) { }这一行表示,创建一个客户端并在花括号{}中执行代码。 然后调用.Dispose()将其关闭。

这意味着您的客户端将根据Dispose()方法的操作而关闭/关闭。

如果要保持连接打开,则不应该using块,或者可以将注入的客户端更改为客户端工厂,让它在每次调用时创建一个新客户端,或者每次使用时手动打开/关闭连接它。

 using (_s3Client){} 

一旦using块完成执行,则将调用dispose方法

使用等于

  var ob = new Object()
 try
 {
   ob = null;
 }
 finally
 {
  if (ob!= null)
    ((IDisposable)ob).Dispose();
 }

使用_s3Client删除,因为将其保留在using块中而已被处置。 因为您的目标是重用它,所以不要简单地对其进行处置。

using (var getObjectResponse = await _s3Client.GetObjectAsync(request))
using (MemoryStream ms = new MemoryStream())
{
    getObjectResponse.ResponseStream.CopyTo(ms);
    FileContentResult download = new FileContentResult(ms.ToArray(), "application/pdf");
    return download.FileContents;
}
  • 如果要将s3Client用作Singleton,请使用using删除。 这样,您将在应用程序生命周期中拥有一个s3Client对象。 如果s3Client在其中存储任何对象,请小心。 这可能会导致资源问题。

    公共类AWSService:IAWSService {私有只读IAmazonS3 _s3Client;

     public AWSService(IAmazonS3 s3Client) { _s3Client = s3Client; } public async Task<byte[]> ReadObjectFromS3Async(string bucketName, string keyName) { try { GetObjectRequest request = new GetObjectRequest { BucketName = bucketName, Key = keyName }; MemoryStream ms = new MemoryStream(); using (var getObjectResponse = await _s3Client.GetObjectAsync(request)) { getObjectResponse.ResponseStream.CopyTo(ms); } var download = new FileContentResult(ms.ToArray(), "application/pdf"); return download.FileContents; } catch (AmazonS3Exception e) { Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message); } catch (Exception e) { Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message); } return null; } 

    }

  • 如果要为每个调用创建一个新对象,请从IOC上下文中删除s3Client注册。

    公共类AWSService:IAWSService {

     public async Task<byte[]> ReadObjectFromS3Async(string bucketName, string keyName) { try { GetObjectRequest request = new GetObjectRequest { BucketName = bucketName, Key = keyName }; using (var s3Client= new s3Client()/*I don't know how you create*/) { MemoryStream ms = new MemoryStream(); using (var getObjectResponse = await s3Client.GetObjectAsync(request)) { getObjectResponse.ResponseStream.CopyTo(ms); } var download = new FileContentResult(ms.ToArray(), "application/pdf"); return download.FileContents; } } catch (AmazonS3Exception e) { Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message); } catch (Exception e) { Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message); } return null; } 

    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM