File: InProcess\Helper.cs
Web Access
Project: src\src\Razor\src\Razor\test\Microsoft.VisualStudio.Razor.IntegrationTests\Microsoft.VisualStudio.Razor.IntegrationTests.csproj (Microsoft.VisualStudio.Razor.IntegrationTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
 
namespace Microsoft.VisualStudio.Razor.IntegrationTests.InProcess;
 
internal static class Helper
{
    /// <summary>
    /// This method will retry the asynchronous action represented by <paramref name="action"/>,
    /// waiting for <paramref name="delay"/> time after each retry. If a given retry returns a value
    /// other than the default value of <typeparamref name="T"/>, this value is returned.
    /// </summary>
    /// <param name="action">the asynchronous action to retry</param>
    /// <param name="delay">the amount of time to wait between retries</param>
    /// <param name="cancellationToken"></param>
    /// <typeparam name="T">type of return value</typeparam>
    /// <returns>the return value of <paramref name="action"/></returns>
    public static Task<T?> RetryAsync<T>(Func<CancellationToken, Task<T>> action, TimeSpan delay, CancellationToken cancellationToken)
    {
        return RetryCoreAsync(
            async cancellationToken =>
            {
                try
                {
                    return await action(cancellationToken);
                }
                catch (COMException)
                {
                    // Devenv can throw COMExceptions if it's busy when we make DTE calls.
                    return default;
                }
            },
            delay,
            cancellationToken);
    }
 
    private static async Task<T> RetryCoreAsync<T>(Func<CancellationToken, Task<T>> action, TimeSpan delay, CancellationToken cancellationToken)
    {
        while (true)
        {
            var retval = await action(cancellationToken);
            if (!Equals(default(T), retval))
            {
                return retval;
            }
 
            await Task.Delay(delay, cancellationToken);
        }
    }
}