Невозможно получить доступ к удаленному объекту при запуске функции более одного раза - PullRequest
0 голосов
/ 07 марта 2019

У меня есть приложение 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;

    }
}

}

При первом запуске функции точка останова показывает, что этот клиент.s3 не удаляется, однако последующие попытки запустить эту функцию показывают, что клиент s3 удаляется, поэтому возникает ошибка.

Обновление

Я вызываю эту функцию из контроллера:

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 ]

2 голосов
/ 07 марта 2019

Это потому, что вы упаковываете использование _s3Client в блок using, который впоследствии удаляет экземпляр.

Не делай этого.

Позвольте вашему контейнеру IoC справиться с этим за вас, без явного или неявного удаления вашего _s3Client.

Можно зарегистрировать вашу обертку как одиночную, учитывая ответ на Безопасен ли поток AmazonSNET AWS SDK для AmazonS3? - это "да". Это означает, что ваше приложение имеет один экземпляр вашего AWSService в любой момент времени, и этот класс будет использовать один и тот же экземпляр IAmazonS3 для всех запросов.

Тогда вам нужно будет утилизировать его только в конце срока службы вашего приложения, и ваш контейнер IoC с этим справится.

1 голос
/ 07 марта 2019
  • Если вы хотите использовать s3Client в качестве Singleton, удалите , используя строку . Таким образом, у вас будет объект 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;
    
    }
    

    }

  • Если вы хотите создавать новый объект для каждого вызова, удалите регистрацию s3Client из контекста IOC.

    открытый класс 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;
    
    }
    

    }

1 голос
/ 07 марта 2019

Удалите, используя _s3Client, который удаляется, когда вы держите его внутри блока использования.Поскольку ваша цель состоит в том, чтобы использовать его повторно, не выбрасывайте, просто.

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;
}
1 голос
/ 07 марта 2019
 using (_s3Client){} 

как только using заблокирует выполнение, тогда будет вызван метод dispose

используя оператор, равный

  var ob = new Object()
 try
 {
   ob = null;
 }
 finally
 {
  if (ob!= null)
    ((IDisposable)ob).Dispose();
 }
1 голос
/ 07 марта 2019

В этой строке using (_s3Client) { } говорится, создайте клиента и выполните код в фигурных скобках {}.Затем вызовите .Dispose(), чтобы закрыть его.

Это означает, что ваш клиент будет закрыт / выключен в зависимости от того, что делает метод Dispose().

Если вы хотите оставить соединение открытым, тоу вас не должно быть блока using, или вы можете изменить встроенный клиент на фабрику клиентов и создать новый каждый вызов или вручную открывать / закрывать соединение каждый раз, когда вы его используете.

1 голос
/ 07 марта 2019

Использование является сокращением для блока try / finally, который вызывает dispose.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...