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

时间:2019-03-07 10:40:57

标签: c# amazon-web-services asp.net-core

我有一个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)
    }
}

6 个答案:

答案 0 :(得分:2)

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

不要那样做。

通过不显式或隐式处理_s3Client来让IoC容器为您处理此问题。

考虑到Is the Amazon .NET AWS SDK's AmazonS3 thread safe?的回答为“是”,可以将包装器注册为单例。这意味着您的应用程序在任何给定时间都有一个AWSService实例,并且该类将对所有请求使用同一IAmazonS3实例。

然后,您只需要在应用程序生命周期结束时对其进行处理,您的IoC容器将对此进行处理。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

 using (_s3Client){} 

一旦using阻止执行完成,然后将调用dispose方法

使用等于

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

答案 4 :(得分:1)

使用_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;
}

答案 5 :(得分:1)

  • 如果要将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;
    
    }
    

    }