Estoy usando .NET para crear un programa de vida artificial y estoy usando la clase pseudoaleatoria de C# definida en Singleton. La idea es que si uso el mismo generador de números aleatorios en toda la aplicación, simplemente podría guardar la semilla y luego volver a cargarla desde la semilla para volver a calcular una determinada ejecución interesante.C# Generador de números aleatorios atorado en un ciclo
public sealed class RandomNumberGenerator : Random
{
private static readonly RandomNumberGenerator instance = new RandomNumberGenerator();
RandomNumberGenerator()
{
}
public static RandomNumberGenerator Instance
{
get
{
return instance;
}
}
}
También quería un método que pudiera darme dos números aleatorios diferentes.
public static Tuple<int, int> TwoDifferentRandomNumbers(this Random rnd, int minValue, int maxValue)
{
if (minValue >= maxValue)
throw new ArgumentOutOfRangeException("maxValue", "maxValue must be greater than minValue");
if (minValue + 1 == maxValue)
return Tuple.Create<int, int>(minValue, maxValue);
int rnd1 = rnd.Next(minValue, maxValue);
int rnd2 = rnd.Next(minValue, maxValue);
while (rnd1 == rnd2)
{
rnd2 = rnd.Next(minValue, maxValue);
}
return Tuple.Create<int, int>(rnd1, rnd2);
}
El problema es que a veces rnd.Next(minValue,maxValue
siempre devuelve minValue
. Si breakpoint en este punto e intento crear un doble y configurarlo en rnd.NextDouble()
, devuelve 0.0. Alguien sabe por qué está pasando esto?
Sé que es un generador de números pseudoaleatorios, pero francamente, no esperaba que se bloqueara en 0. Se está accediendo al generador de números aleatorios desde varios hilos ... ¿podría ser esta la causa del problema? ?
EDITAR: Gracias, el problema terminó siendo la seguridad del hilo.
Esta es la nueva versión de la clase.
public sealed class RandomNumberGenerator : Random
{
private static Random _global = new Random();
[ThreadStatic]
private static Random _localInstance;
RandomNumberGenerator()
{
}
public static Random Instance
{
get
{
Random inst = _localInstance;
if (inst == null)
{
int seed;
lock (_global) seed = _global.Next();
_localInstance = inst = new Random(seed);
}
return _localInstance;
}
}
}
¡Ups, había dejado esta ventana de respuesta de publicación abierta un poco demasiado, +1 ... esto es exactamente lo que quería decir! –
Gracias, estabas exactamente en lo cierto. Acepté tu comentario como respuesta para darte un poco más de karma: P Además, gracias por contarme sobre el otro asunto de múltiples hilos, ¡no se me había pasado por la cabeza! –