// 以下是最初的问题,但解决方案与使用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;
}
}
}
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