0

I am using the following code to generate a unique Application InstanceID for logging.

public MainWindow()
{
    InitializeComponent();

    Random rnd = new Random();

    instanceID = rnd.Next(100000, 999999);

    /// ...
}

my App starts with a windowsserver as different services (with nssm) 2 and more Times with different Parameters. My Problem: if they start at the same time (same second), instanzID is the same, if 1 or more second difference instanzID is different. How can i avoid this?

user3600403
  • 339
  • 1
  • 2
  • 18
  • 8
    *"to generate a unique Application InstanceID"* - The semantics are important. "Random" and "unique" are two very different things. Perhaps use a `Guid` instead? – David Oct 24 '19 at 13:19
  • Thank you, i changed to Guid.NewGuid and will test it next time – user3600403 Oct 25 '19 at 14:13

2 Answers2

2

Well, Random is not thread safe (you've mentioned "server as different services"), that's why let each thread has its own Random instance:

private static ThreadLocal<Random> MyRandom = ...

Since we don't want all these instances generate the same sequences, let's provide an entropy source, we can do it with a help of RNGCryptoServiceProvider:

using System.Security.Cryptography;
using System.Threading;

...  

private static ThreadLocal<Random> MyRandom = new ThreadLocal<Random>(() => {
  int seed;

  using (RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider()) {
    byte[] seedData = new byte[sizeof(int)];

    provider.GetBytes(seedData);

    seed = BitConverter.ToInt32(seedData, 0);
  }

  return new Random(seed);
});

Now, MyRandom is thread safe and each thread has its own (pseudo-)random sequence.

instanzID = MyRandom.Next(100000, 999999);
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • I don't think the problem is about using the same `Random` instance from different threads. The problem is that independent `Random` instances instantiated at the same time in different processes can be seeded with the same value. Seeding with `RNGCryptoServiceProvider` is a solution, but I don't think the `ThreadLocal` is relevant to the OP's question. – canton7 Oct 24 '19 at 13:43
  • Yes, canton7 is right, i edited the question for better understanding. – user3600403 Oct 25 '19 at 14:19
0

By default the Random object uses the current time as the initial seed. To do what you want, just provide an int in the constructor as Random rnd = new Random(seed) where seed is the initial seed of the algorithm. As long as seed is the same for all of your Random objects, they will produce the same sequence of random numbers.

Javier Silva Ortíz
  • 2,864
  • 1
  • 12
  • 21