public async ValueTask <string> GetHeaderValueAsync(HttpMessage message, bool async) { bool getTokenFromCredential; TaskCompletionSource <HeaderValueInfo> headerValueTcs; TaskCompletionSource <HeaderValueInfo>?backgroundUpdateTcs; (headerValueTcs, backgroundUpdateTcs, getTokenFromCredential) = GetTaskCompletionSources(); if (getTokenFromCredential) { if (backgroundUpdateTcs != null) { #pragma warning disable AZC0111 // DO NOT use EnsureCompleted in possibly asynchronous scope. HeaderValueInfo info = headerValueTcs.Task.EnsureCompleted(); #pragma warning restore AZC0111 // DO NOT use EnsureCompleted in possibly asynchronous scope. _ = Task.Run(() => GetHeaderValueFromCredentialInBackgroundAsync(backgroundUpdateTcs, info, message, async)); return(info.HeaderValue); } try { HeaderValueInfo info = await GetHeaderValueFromCredentialAsync(message, async, message.CancellationToken).ConfigureAwait(false); headerValueTcs.SetResult(info); } catch (OperationCanceledException) { headerValueTcs.SetCanceled(); throw; } catch (Exception exception) { headerValueTcs.SetException(exception); throw; } } var headerValueTask = headerValueTcs.Task; if (!headerValueTask.IsCompleted) { if (async) { await headerValueTask.AwaitWithCancellation(message.CancellationToken); } else { try { headerValueTask.Wait(message.CancellationToken); } catch (AggregateException) { } // ignore exception here to rethrow it with EnsureCompleted } } #pragma warning disable AZC0111 // DO NOT use EnsureCompleted in possibly asynchronous scope. return(headerValueTcs.Task.EnsureCompleted().HeaderValue); #pragma warning restore AZC0111 // DO NOT use EnsureCompleted in possibly asynchronous scope. }
public async ValueTask <string> GetHeaderValueAsync(HttpMessage message, bool async) { bool getTokenFromCredential; TaskCompletionSource <HeaderValueInfo> headerValueTcs; TaskCompletionSource <HeaderValueInfo>?backgroundUpdateTcs; int maxCancellationRetries = 3; while (true) { (headerValueTcs, backgroundUpdateTcs, getTokenFromCredential) = GetTaskCompletionSources(); if (getTokenFromCredential) { if (backgroundUpdateTcs != null) { #pragma warning disable AZC0111 // DO NOT use EnsureCompleted in possibly asynchronous scope. HeaderValueInfo info = headerValueTcs.Task.EnsureCompleted(); #pragma warning restore AZC0111 // DO NOT use EnsureCompleted in possibly asynchronous scope. _ = Task.Run(() => GetHeaderValueFromCredentialInBackgroundAsync(backgroundUpdateTcs, info, message, async)); return(info.HeaderValue); } try { HeaderValueInfo info = await GetHeaderValueFromCredentialAsync(message, async, message.CancellationToken).ConfigureAwait(false); headerValueTcs.SetResult(info); } catch (OperationCanceledException) { headerValueTcs.SetCanceled(); } #pragma warning disable CA1031 // Catch more specific allowed exception type, or rethrow the exception catch (Exception exception) #pragma warning restore CA1031 // Catch more specific allowed exception type, or rethrow the exception { headerValueTcs.SetException(exception); // The exception will be thrown on the next lines when we touch the result of // headerValueTcs.Task, this approach will prevent later runtime UnobservedTaskException } } var headerValueTask = headerValueTcs.Task; try { if (!headerValueTask.IsCompleted) { if (async) { await headerValueTask.AwaitWithCancellation(message.CancellationToken); } else { try { headerValueTask.Wait(message.CancellationToken); } catch (AggregateException) { } // ignore exception here to rethrow it with EnsureCompleted } } #pragma warning disable AZC0111 // DO NOT use EnsureCompleted in possibly asynchronous scope. return(headerValueTcs.Task.EnsureCompleted().HeaderValue); #pragma warning restore AZC0111 // DO NOT use EnsureCompleted in possibly asynchronous scope. } catch (TaskCanceledException) when(!message.CancellationToken.IsCancellationRequested) { maxCancellationRetries--; // If the current message has no CancellationToken and we have tried this 3 times, throw. if (!message.CancellationToken.CanBeCanceled && maxCancellationRetries <= 0) { throw; } // We were waiting on a previous headerValueTcs operation which was canceled. //Retry the call to GetTaskCompletionSources. continue; } } }