Skip to main content

Represents a thread-safe, pseudo-random number generator.

//--------------------------------------------------------------------------
//
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//
//  File: ThreadSafeRandom.cs
//
//--------------------------------------------------------------------------

using System;
using System.Security.Cryptography;

namespace System.Threading
{
    /// <inheritdoc />
    /// <summary>
    /// Represents a thread-safe, pseudo-random number generator.
    /// </summary>
    public class ThreadSafeRandom : Random
    {
        /// <summary>Seed provider.</summary>
        private static readonly RNGCryptoServiceProvider CryptProvider = new RNGCryptoServiceProvider();

        /// <summary>The underlyin provider of randomness, one instance per thread, initialized with CryptProvider.</summary>
        private readonly ThreadLocal<Random> _local = new ThreadLocal<Random>(() =>
        {
            var buffer = new byte[4];
            CryptProvider.GetBytes(buffer); // RNGCryptoServiceProvider is thread-safe for use in this manner
            return new Random(BitConverter.ToInt32(buffer, 0));
        });

        /// <inheritdoc />
        /// <summary>Returns a nonnegative random number.</summary>
        /// <returns>A 32-bit signed integer greater than or equal to zero and less than MaxValue.</returns>
        public override int Next()
        {
            return _local.Value.Next();
        }

        /// <inheritdoc />
        /// <summary>Returns a nonnegative random number less than the specified maximum.</summary>
        /// <param name="maxValue">
        /// The exclusive upper bound of the random number to be generated. maxValue must be greater than or equal to zero.
        /// </param>
        /// <returns>
        /// A 32-bit signed integer greater than or equal to zero, and less than maxValue;
        /// that is, the range of return values ordinarily includes zero but not maxValue. However,
        /// if maxValue equals zero, maxValue is returned.
        /// </returns>
        public override int Next(int maxValue)
        {
            return _local.Value.Next(maxValue);
        }

        /// <inheritdoc />
        /// <summary>Returns a random number within a specified range.</summary>
        /// <param name="minValue">The inclusive lower bound of the random number returned.</param>
        /// <param name="maxValue">The exclusive upper bound of the random number returned. maxValue must be greater than or equal to minValue.</param>
        /// <returns>
        /// A 32-bit signed integer greater than or equal to minValue and less than maxValue;
        /// that is, the range of return values includes minValue but not maxValue.
        /// If minValue equals maxValue, minValue is returned.
        /// </returns>
        public override int Next(int minValue, int maxValue)
        {
            return _local.Value.Next(minValue, maxValue);
        }

        /// <inheritdoc />
        /// <summary>Returns a random number between 0.0 and 1.0.</summary>
        /// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0.</returns>
        public override double NextDouble()
        {
            return _local.Value.NextDouble();
        }

        /// <inheritdoc />
        /// <summary>Fills the elements of a specified array of bytes with random numbers.</summary>
        /// <param name="buffer">An array of bytes to contain random numbers.</param>
        public override void NextBytes(byte[] buffer)
        {
            _local.Value.NextBytes(buffer);
        }
    }
}