// 以下是最初的问题,但解决方案与使用ZipArchive类相关联,以将多个流获取到多个文件,并在多个线程中使用它们.真正的问题和答案在"回答"帖子中. //

我有个很复杂的案子...我正在从其他API调用我自己的API.我一次做六次.在第一次调用时,我需要获取一个Access令牌并缓存它,以便所有其他请求都可以使用它.如果我将同步执行第一次调用,然后立即异步执行其余5次调用-一切都正常.但所有6次-我收到一个错误从SendAsync(与访问令牌生成正确):

The archive entry was compressed using an unsupported compression method.

如果我从我的代码中删除SemaphoreSlim,所有6个调用都会自己生成token(因为所有调用都无法从缓存中获取它),那么它也可以工作. token的代码(这个类是 for each 请求单独创建的,这就是为什么semaphore是静态的):

public class AzureCredentialCached : ChainedTokenCredential
{
    private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);

    public override async ValueTask<AccessToken> GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken = default)
    {
        AccessToken? cachedToken = _cacheService.TryGetToken(requestContext, _uri);
        if (cachedToken is null)
        {
            await _semaphore.WaitAsync(cancellationToken);
            try
            {
                cachedToken = _cacheService.TryGetToken(requestContext, _uri);
                if (cachedToken is null)
                {
                    cachedToken = await base.GetTokenAsync(requestContext, cancellationToken);
                    _cacheService.InsertNewToken((AccessToken)cachedToken, requestContext, _uri);
                }
            }
            finally
            {
                _semaphore.Release();
            }
        }

        return (AccessToken)cachedToken;
    }
}

委派处理程序:

public class StorageApiAuthorizeRequestHandler : DelegatingHandler
{
    private readonly IAzureCredentialCacheService _credentialCacheService;
    private readonly GeneralSection _generalConfig;
    private readonly StorageApiSection _storageConfig;

    public StorageApiAuthorizeRequestHandler(IAzureCredentialCacheService credentialCacheService, IOptions<StorageApiSection> storageConfig, IOptions<GeneralSection> generalConfig)
    {
        _credentialCacheService = credentialCacheService;
        _generalConfig = generalConfig.Value;
        _storageConfig = storageConfig.Value;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var credential = new AzureCredentialCached(_credentialCacheService, new Uri(_storageConfig.Address, UriKind.Absolute), new Azure.Core.TokenCredential[]
        {
            new ManagedIdentityCredential(_generalConfig.ManagedIdentityClientId),
            new VisualStudioCredential()
        });

        var scopes = new[] { _storageConfig.Scope };
        var accessToken = (await credential.GetTokenAsync(new Azure.Core.TokenRequestContext(scopes))).Token;

        request.Headers.Add(HeaderNames.Authorization, $"Bearer {accessToken}");

        try
        {
            return await base.SendAsync(request, cancellationToken);
        }
        catch (Exception ex)
        {
            throw;
        }
    }
}

enter image description here

The archive entry was compressed using an unsupported compression method.
 at System.IO.Compression.Inflater.Inflate(FlushCode flushCode)
   at System.IO.Compression.Inflater.ReadInflateOutput(Byte* bufPtr, Int32 length, FlushCode flushCode, Int32& bytesRead)
   at System.IO.Compression.Inflater.ReadOutput(Byte* bufPtr, Int32 length, Int32& bytesRead)
   at System.IO.Compression.Inflater.InflateVerified(Byte* bufPtr, Int32 length)
   at System.IO.Compression.DeflateStream.CopyToStream.<WriteAsyncCore>d__10.MoveNext()
   at System.IO.Stream.<<CopyToAsync>g__Core|29_0>d.MoveNext()
   at System.IO.Compression.DeflateStream.CopyToStream.<CopyFromSourceToDestinationAsync>d__6.MoveNext()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter.GetResult()
   at System.Net.Http.HttpContent.<<CopyToAsync>g__WaitAsync|56_0>d.MoveNext()
   at System.Net.Http.MultipartContent.<SerializeToStreamAsyncCore>d__23.MoveNext()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter.GetResult()
   at System.Net.Http.HttpContent.<<CopyToAsync>g__WaitAsync|56_0>d.MoveNext()
   at System.Net.Http.HttpConnection.<SendRequestContentAsync>d__70.MoveNext()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter.GetResult()
   at System.Net.Http.HttpConnection.<SendAsyncCore>d__64.MoveNext()
   at System.Net.Http.HttpConnection.<SendAsyncCore>d__64.MoveNext()
   at System.Net.Http.HttpConnectionPool.<SendWithVersionDetectionAndRetryAsync>d__84.MoveNext()
   at System.Net.Http.DiagnosticsHandler.<SendAsyncCore>d__8.MoveNext()
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable`1.ConfiguredValueTaskAwaiter.GetResult()
   at System.Net.Http.RedirectHandler.<SendAsync>d__4.MoveNext()
   at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.<SendAsync>d__5.MoveNext()
   at MyAPP.ApiAuthentication.StorageApiAuthorizeRequestHandler.<SendAsync>d__4.MoveNext() in C:\MyAPP\ApiAuthentication\StorageApiAuthorizeRequestHandler.cs:line 37

推荐答案

这个问题实际上与我发送的内容有关.我们正在使用ZipArchive类从ZIP存档中提取文件,并将它们上传到我们的另一个API.所以流程是这样的:

  1. 我正在以ZIP格式打开文件流

    Var Entry=_zipArchive.GetEntry(路径); 进入.打开();

  2. 我正在使用请求中的此流执行SendAsync

  3. 将另一个全新的流打开到另一个文件

  4. 我正在使用请求中的此流执行SendAsync ...

  5. 同时,第二个API启动并加载配置.它接收多个请求,但由于信号量,每个请求都在等待第一个请求从Azure加载应用程序配置

  6. 当它完成时,它try 同时从第一个API拉取流

  7. 看起来甚至不能同时使用ZipArchive库中的不同流.SendAsync抛出异常,因为我认为这些流是动态解压缩的,并且以某种方式彼此相交.

解决方案是将所有这些流复制到一个单独的内存流中(多亏了这一点,它们首先被逐个解压缩).现在,所有SendAsync同时工作,没有任何问题...

Csharp相关问答推荐

获取ASP.NET核心身份认证cookie名称

向类注入一个工厂来创建一些资源是一个好的实践吗?

什么是通过反射创建类的泛型接口方法的正确方法?

. net依赖注入如何避免服务类中的新

如何在不考虑年份的情况下判断日期时间是否在某个日期范围内?

如何测量在使用UTF8而不是C#中的UTF16编码字符串时内存使用量的增长

从ASP.NET Core中的枚举字段填充 Select 选项时,将默认的第一个选项添加为 Select 元素

C# CompareTo()和Compare()可以返回除-1和1以外的整数吗?

C#中Java算法的类似功能

使用CollectionView时在.NET Maui中显示数据时出现问题

我什么时候应该在Dapper中使用Connection.OpenAsync?

如何在microsoft.clearscript.v8的jsondata中使用Linq

C#LINQ子字符串

未在Windows上运行的Maui项目

错误:此版本的Visual Studio无法打开以下项目

用MongoDB c#驱动程序删除和返回嵌套数组中的文档

具有嵌套属性的IGGroup

Unity 3D-意外轴捕捉和未知力对脉冲react 行为的影响

能否将我图表中的星号与X轴上一天中的第二位数字对齐?

PowerShell:如何[引用]数组中的元素?