1

I am trying to fully understand something that seems quite mystical at this point after an hour analysis. Please bear with the detailed explanation.

I got a function in my asp.net mvc4 application.

    private string GenerateDownloadCode(int id, int organizationId)
    {
        const int downloadCodeMinValue = 10000000;
        const int downloadCodeMaxValue = 20000000;

        int number = new Random().Next(downloadCodeMinValue, downloadCodeMaxValue);
        return string.Format("{0}-{1}-{2}", id, organizationId, number);
    }

The function is used to generate a random number for download code. I noticed that the number value is always equal to downloadCodeMinValue.

I checked the MSDN and dig into the implementation of Next method in framework code which looks like:

      long range = (long)maxValue-minValue;
      if( range <= (long)Int32.MaxValue) {  
          return ((int)(Sample() * range) + minValue);
      }          
      else { 
          return (int)((long)(GetSampleForLargeRange() * range) + minValue);
      }

Sample() method can return a value 0.0 to 1.0 and I think in my case it is always returning 0.0 causing this method to return minValue. Ok it is a "legal value for the Random number".

I can live with that until I pick up my method and copied it into LINQPad where it is generating a random number consistently.

Q1: Why same method return expected random number in LINQPad?

I read some questions around this (very close to my problem, MVC specific but does not consider my case) that explains Random class behavior and offer some solutions.

The above links assume the code is invoked in a close loop or shorter time period, in my case this method is called at least minute difference if not hour.

I do not have a problem with getting same number back so do not want to fix the code, inability and curiosity to understand WHY it is not working in an MVC app (each request is served in a new thread) making me reach to the experts here.

Q2: So what could be the reason the the method does not return random number in an MVC app?

Update:

Context for the method - This method is used to generate a new random long (>= 12 char) enough number for each new organization added. Hence each call is minutes delayed.

Update 2:

The method is called from a method AddOrganizationUser that exist in a different library (business or service). The service method is invoked from controller action

    public ActionResult CreateUser(OrganizationUserViewModel ouser)
        {    
            organizationUserService.AddOrganizationUser(organizationUserDomainModel, loggedInUser.Id);    
        }
Community
  • 1
  • 1
SBirthare
  • 5,117
  • 4
  • 34
  • 59
  • @AnantDabhi - I have that link in my question and i think it is not a duplicate. Please read full question. – SBirthare Nov 19 '14 at 11:33
  • Have you tried making a variable to contain 'new Random()' as a static variable? – Vsevolod Goloviznin Nov 19 '14 at 11:34
  • It's giving you different numbers in Linqpad because you waited more than 10 milliseconds or so between generating the numbers. – Matthew Watson Nov 19 '14 at 11:37
  • @MatthewWatson, OP claims that number is the same in two calls with an hour between them. If this is indeed so, this question is definitely not a duplicate – Andrei Nov 19 '14 at 11:41
  • Could you please provide a context of the `GenerateDownloadCode` call in your mvc app? – Andrei Nov 19 '14 at 11:43
  • @Andrei - I will update my question. This method is used to generate a new random long (>= 12 char) enough number for each new organization added. Hence each call is minutes delayed. – SBirthare Nov 19 '14 at 11:48
  • @SBirthare, that is not what I meant by context. Can you post the code where you call it, with some context around? – Andrei Nov 19 '14 at 11:52
  • @MatthewWatson - Not quite right. I looped 1000 times and it still returned random value and was finished in .025 seconds. – SBirthare Nov 19 '14 at 11:53
  • It may well produce duplicates occasionally, but it won't all the time. Are you saying that however many times you call it, it produces the same number? Because I've tried your code, and it certainly doesn't (if you sleep for a few milliseconds inbetween or reuse the same Random object) – Matthew Watson Nov 19 '14 at 11:57
  • @Andrei - I added more information. – SBirthare Nov 19 '14 at 11:59
  • Perhaps you should write a console app that reproduces the problem, and then post the code in a new question. – Matthew Watson Nov 19 '14 at 11:59
  • @SBirthare I just tested with console app and its working fine .. and I dont think .net framework behave diffrent for mvc and console app.. – Anant Dabhi Nov 19 '14 at 11:59
  • Yes, I cannot reproduce this either. – Matthew Watson Nov 19 '14 at 12:00
  • @MatthewWatson - I am considering LINQPad is not different than a console app. It is using same .net framework libraries I believe. So my observation is same that the code works outside MVC env. – SBirthare Nov 19 '14 at 12:01
  • I am going to try in a new MVC app and let you know the result. – SBirthare Nov 19 '14 at 12:02
  • There must be a bug elsewhere in your code; the code you have posted works correctly. The Random class doesn't work differently from an MVC perspective - but perhaps you have a multithreading bug or something. – Matthew Watson Nov 19 '14 at 12:02
  • @MatthewWatson - Thank you, I think I am after that bug only :). I am checking in a separate MVC app. Do you think DI can lead to any problem? – SBirthare Nov 19 '14 at 12:07
  • DI could cause issues if the item being injected is in use by other threads, or is being changed from outside the consumer. – Matthew Watson Nov 19 '14 at 12:13

1 Answers1

1

I think u are calling this from a multi-threaded environment? Random is not thread safe.

Here are a number of ways to implement a thread safe random. http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx

Hope this helps

EDIT: Also creating a new random for each random number is bad practice.

Sandip Armal Patil
  • 6,241
  • 21
  • 93
  • 160
sQuir3l
  • 1,373
  • 7
  • 12
  • In the specific example code, a new Random is created for each call, so there will be no multithreading issues with Random itself - but there might well be multithreading issues with the other code. – Matthew Watson Nov 19 '14 at 12:39