tags:

views:

222

answers:

2

I have a method in a singleton class that need to use the .NET System. Random(), since the method is called in a multi-threaded environment I can't create it only once and declare it statically, but I have to create a Random() object each time the method is called. Since Random() default seed is based on the clock ticks it is not random enough in my senario. To create a better seed I have looked into several methods and have figured the following one is the best, but there may be other (faster/better) ways of doing this that I would like to know about.

Random rnd = new Random(BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0));
+6  A: 

Instead of trying to come up with a better seed yourself, use System.Security.Cryptography.RandomNumberGenerator.

It uses a seed based on a complex algorithm that involves a lot of different environment variables. System time is one of those, as is IIRC the MAC address of your NIC, etc.

It is also considered a 'more random' algorithm than the one implemented by the Random class.

Mark Seemann
Minor clarification: As RandomNumberGenerator is an abstract class, he'd actually use System.Security.Cryptography.RNGCryptoServiceProviderAnd he should be sure that if his singleton allows multiple simultaneous users (getInstance isn't inherently synchronized), that he protects usage of the non-static members of RNGCryptoServiceProvider, since they're not thread-safe.
CPerkins
@CPerkins: Good points - thanks!
Mark Seemann
+3  A: 

Create it statically and use a lock to make it thread safe:

public static class RandomProvider {

   private static Random _rnd = new Random();
   private static object _sync = new object();

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

   public static int Next(int max) {
      lock (_sync) {
         return _rnd.Next(max);
      }
   }

   public static int Next(int min, int max) {
      lock (_sync) {
         return _rnd.Next(min, max);
      }
   }

}

If you still need a Random object in each thread for some reason, you could use the static class to seed them:

Random r = new Random(RandomProvider.Next() ^ Environment.TickCount);
Guffa