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.
            }
示例#2
0
            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;
                    }
                }
            }