2

Aside from using the System.Random inherent in the C# library, How would you transfer this properly (or the best way.) to C# in MVC4. System.Random seems far to clunky and burdensome because if the method gets called in short succession, the number doesn't become random.

The other problem I'm having is that the System.Random method requires a Min and a Max, if the Database that I'm going to be holding the Quotation strings in keeps growing, how to properly adjust for the size?

This is the original JavaScript code.

var which = Math.round(Math.random()*(Quotation.length - 1));

I'm trying to reproduce this JavaScript code to have better functionality by pulling from a model that can constantly be updated with new Quotation. I don't want to have to keep changing this code:

int ranNum;
Random random = new Random();
ranNum = random.Next(1,7);

every time the quotations increase... Right now, it's going to list any of the 7 Quotation Strings, but if the Database increases in Quotation from 7 to 9, I'll have to go back and change the 7 to a 9, and so on and so forth. This is tedious, There has to be a better way.

Here is the original JavaScript code:

<script language="JavaScript">
function rotateEvery(sec)
{
var Quotation=new Array()
// QUOTATIONS
Quotation[0] = '<p>A journey of a thousand li begins with a single step.</p> Confucian Proverb.';
Quotation[1] = '<p>A picture is worth a thousand words.</p> Confucian Proverb.';
Quotation[2] = '<p>After all I have no nationality and am not anxious to claim any. Individuality is more than nationality.</p> Confucian Proverb.';
Quotation[3] = '<p>Be not ashamed of mistakes and thus make them crimes.</p> Confucian Proverb.';
Quotation[4] = '<p>He who counsels himself, counsels a fool.</p> Confucian Proverb.';
Quotation[5] = '<p>If thy strength will serve, go forward in the ranks; if not, stand still.</p> Confucian Proverb.';
Quotation[6] = '<p>Train equally the mind and body.</p> Confucian Proverb.';
var which = Math.round(Math.random()*(Quotation.length - 1));
document.getElementById('textrotator').innerHTML = Quotation[which];
setTimeout('rotateEvery('+sec+')', sec*1000);
}
</script>

Thank you in advance.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
user1760784
  • 119
  • 3
  • 12

1 Answers1

7

System.Random seems far to clunky and burdensome because if the method gets called in short succession, the number doesn't become random.

That just means you're using it incorrectly, basically. You shouldn't be creating a new instance each time you want a random number - you should reuse an existing instance. However, you need to be careful, because Random isn't thread-safe. You basically want a single instance per thread or (more simply but less efficiently) a single instance shared between threads, with locking to avoid thread safety issues.

I have an article which goes into a lot more detail, but here's a code sample from it that you can use to get an appropriate Random instance for any thread:

using System;
using System.Threading;

public static class RandomProvider
{    
    private static int seed = Environment.TickCount;

    private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>(() =>
        new Random(Interlocked.Increment(ref seed))
    );

    public static Random GetThreadRandom()
    {
        return randomWrapper.Value;
    }
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks Skeet :) Small question though: could you use a `get;` only property instead or does that have problems? – It'sNotALie. Jun 26 '13 at 19:55
  • @newStackExchangeInstance: Yes, you could certainly use a property - but it could be a bit confusing for a property to give different values like that. Ask me on another day and I might code it as a property, mind you... – Jon Skeet Jun 26 '13 at 20:01
  • What's the difference between `[ThreadStatic]` and `ThreadLocal`? – jgauffin Jun 26 '13 at 20:02
  • +1. Nice code/nice article promotion :). Also should simply be duplicate of http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number. – Alexei Levenkov Jun 26 '13 at 20:14
  • The above code is confusing the ever living daylights out of me. This doesn't look like anything I'm use to in the normal System.Random. Where does the Max/Min come into play? From what I see here it'll auto increment, am I correct? – user1760784 Jun 26 '13 at 20:30
  • 2
    @user1760784 Max/Min come in to play when you call `GetThreadRandom` to get an instance of Random. You would next call `Next` on it (or whatever) with your min and max values. All this code is doing is creating a reusable per-thread instance of Random (because Random isn't thread safe, and a per-thread instance is more efficient than locking a single one). It uses the interlocked.increment on the seed to ensure that if two threads create a random instance at nearly the exact same time (to where the tick count is the same) they still get separate seeds. – vcsjones Jun 26 '13 at 20:58
  • Thank you for the clarification VCSJones, that makes a lot more sense. – user1760784 Jun 26 '13 at 23:59