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