diff --git a/Box.V2/Box.V2.csproj b/Box.V2/Box.V2.csproj index 8cfd492d3..380a2a750 100644 --- a/Box.V2/Box.V2.csproj +++ b/Box.V2/Box.V2.csproj @@ -276,6 +276,7 @@ + @@ -343,4 +344,4 @@ - \ No newline at end of file + diff --git a/Box.V2/Utility/ExponentialBackoff.cs b/Box.V2/Utility/ExponentialBackoff.cs index aa06edbe7..55f29d569 100644 --- a/Box.V2/Utility/ExponentialBackoff.cs +++ b/Box.V2/Utility/ExponentialBackoff.cs @@ -10,9 +10,10 @@ public TimeSpan GetRetryTimeout(int numRetries) const double RETRY_RANDOMIZATION_FACTOR = 0.5; var minRandomization = 1 - RETRY_RANDOMIZATION_FACTOR; var maxRandomization = 1 + RETRY_RANDOMIZATION_FACTOR; - var random = new Random(); - var randomization = random.NextDouble() * (maxRandomization - minRandomization) + minRandomization; + var randomization = ThreadSafeRandom.Instance.NextDouble() + * (maxRandomization - minRandomization) + minRandomization; + var exponential = Math.Pow(2, numRetries - 1); var result = Math.Ceiling(exponential * baseInterval.TotalSeconds * randomization); return TimeSpan.FromSeconds(result); diff --git a/Box.V2/Utility/ThreadSafeRandom.cs b/Box.V2/Utility/ThreadSafeRandom.cs new file mode 100644 index 000000000..76ac32324 --- /dev/null +++ b/Box.V2/Utility/ThreadSafeRandom.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Box.V2.Utility +{ + /// + /// A thread safe implementation of , following best practices + /// for .NET Framework and .NET Standard. + /// + /// + internal static class ThreadSafeRandom + { + // + // Adapted from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Random.cs + // + // NOTE: when/if this library updates to .NET 6+, this code can be replaced with `Random.Shared` + // + + [ThreadStatic] + private static Random _random; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Random CreateRandom() => _random = new Random(); + + /// + /// An instance of specific to the calling thread. + /// Do not pass this instance to other threads or contexts. + /// + public static Random Instance => _random ?? CreateRandom(); + } +}