6
votes

C # aléatoire.Next arrête soudainement de retourner des valeurs aléatoires

Dupliqué possible:
System.Random continue à retourner la même valeur

Je refactore et développe un petit modèle d'agent C # pour aider certains professeurs de biologie à prédire la propagation d'une maladie. Chaque année de la simulation Chaque agent se déplace au hasard vers un nœud de population à proximité, éventuellement propager la maladie. Je suis tout neuf à C #, mais j'ai lu sur les problèmes potentiels avec Room.Suivant renvoyer la même valeur si réinitialisé avec le même temps de système. Pour éviter cela, j'ai créé une instance statique qui est référencée pour chaque nouvelle valeur aléatoire.

Les spécificités:

Dans mes efforts pour augmenter le modèle, je l'ai changé pour calculer les informations "Voyage" pour chaque noeud de population en parallèle. Lorsque vous testez le modèle, j'ai remarqué que dans la nouvelle version, la maladie ne se répandrait pas après la première année. Une autre enquête a réduit le problème jusqu'au voyage entre les nœuds. Après la première année, tous les agents sont restés immobiles. J'ai examiné la fonction responsable de leur voyage et j'ai constaté qu'il fonctionne en créant une liste de tous les nœuds à proximité, générant un nombre aléatoire <= le nombre d'éléments de la liste et voyager à ListOfnearbynodes [Myrandomnumber].

Le problème:

J'ai ensuite ajouté une instruction d'impression pour émettre la valeur de l'index aléatoire pour chaque itération. J'ai constaté que l'ensemble du modèle fonctionne exactement comme prévu pour la première année de la simulation, les numéros aléatoires étant générés dans une plage acceptable. Cependant, après la fin de la première année et la simulation boucle le même code, le même code ne renvoie qu'un indice "aléatoire" de 0. Chaque thread, chaque itération, chaque nœud, chaque agent, toujours 0. Comme le nœud actuel d'un agent est toujours Le premier élément de la liste Les agents ne se déplacent plus jamais.

Je pensais que cela pourrait être une autre manifestation de l'erreur de graines de temps système, j'ai donc essayé trois manières différentes de mettre en œuvre un objet aléatoire statique, mais cela n'aide pas. Chaque fois que j'exécute la simulation, la première année fonctionne toujours correctement puis aléatoire.Next () commence à renvoyer uniquement 0.

Quelqu'un a-t-il des idées sur les endroits où je devrais regarder ensuite pour le bogue? Merci!


2 commentaires

Un échantillon de code court mais complet, les reproduits l'erreur seraient utiles pour vous et la communauté afin de vous aider à diagnostiquer le problème.


J'ai posé une question à laquelle je pense est liée et peut aider: Stackoverflow.com/Questtions/2924599/...


4 Réponses :


21
votes

Je soupçonne que vous utilisez la même instance de aléatoire simultanément dans plusieurs threads. Ne faites pas ça - ce n'est pas le fil-faire.

Options:

  • Créer une nouvelle instance de aléatoire par thread ( threadstatic peut vous aider ici)
  • Utilisez une seule instance de aléatoire , mais ne l'utilise que dans une serrure.

    J'ai un Publication du blog avec Quelques échantillons de code, mais veuillez lire les commentaires aussi bien que de bonnes suggestions pour l'améliorer. Je prévois d'écrire un autre article sur le hasard à un moment donné dans le futur proche ISH ...


0 commentaires

6
votes

Je ne crois pas que la classe aléatoire soit conçue pour être un fil de sécurité (simultanément utilisable de plusieurs threads) - donc si vous partagez une seule instance de cette manière, vous pouvez corrompre l'état du générateur aléatoire, empêchant ainsi de fonctionner correctement.

Vous pouvez décorer la variable statique qui contient la référence à la classe aléatoire comme threadstatique code>, ce qui vous permettra de maintenir une instance séparée par thread: p>

[ThreadStatic]
private static Random m_Random;  // don't attempt to initialize this here...

public void YourThreadStartMethod()
{
    // initialize each random instance as each thread starts...
    m_Random = new Random();
}


0 commentaires

1
votes

Je pense que vous devriez plutôt utiliser le rngcryptoserviceProvider

http://msdn.microsoft.com /en-us/library/system.security.cryptography.rngCryptoserviceProvider.aspx


0 commentaires

2
votes

Le objet aléatoire code> n'est pas le fil sûr. Pour contourner cela, vous pouvez utiliser ce code volé depuis Cette réponse A>:

class ThreadSafeRandom 
{ 
    private static Random random = new Random(); 

    public static int Next() 
    { 
       lock (random) 
       { 
           return random.Next(); 
       } 
    } 
}


0 commentaires