Reputation: 249
I'm trying to get a randomly picked background image (from a selection of 4 images) to appear as the background image for a asp.net panel.
The problem I have is that the code works when stepping through the code in debug mode. Once you run the code on the website without debugging, all the images are the same. Its almost as if the random number is not getting picked up quick enough.
The usercontrol is inside of a datalist.
The usercontrol is this:
<asp:Panel ID="productPanel" CssClass="ProductItem" runat="server">
<div class="title" visible="false">
<asp:HyperLink ID="hlProduct" runat="server" />
</div>
<div class="picture">
<asp:HyperLink ID="hlImageLink" runat="server" />
</div>
<div class="description" visible="false">
<asp:Literal runat="server" ID="lShortDescription"></asp:Literal>
</div>
<div class="addInfo" visible="false">
<div class="prices">
<asp:Label ID="lblOldPrice" runat="server" CssClass="oldproductPrice" />
<br />
<asp:Label ID="lblPrice" runat="server" CssClass="productPrice" /></div>
<div class="buttons">
<asp:Button runat="server" ID="btnProductDetails" OnCommand="btnProductDetails_Click"
Text="Details" ValidationGroup="ProductDetails" CommandArgument='<%# Eval("ProductID") %>'
SkinID="ProductGridProductDetailButton" /><br />
<asp:Button runat="server" ID="btnAddToCart" OnCommand="btnAddToCart_Click" Text="Add to cart"
ValidationGroup="ProductDetails" CommandArgument='<%# Eval("ProductID") %>' SkinID="ProductGridAddToCartButton" />
</div>
</div>
and the code behind is this:
protected void Page_Load(object sender, EventArgs e)
{
// Some code here to generate a random number between 0 & 3
System.Random RandNum = new System.Random();
int myInt = RandNum.Next(4);
if (productPanel.BackImageUrl != null)
{
switch (myInt)
{
case 0:
productPanel.BackImageUrl = "../App_Themes/emmaharris/images/frame1.gif";
break;
case 1:
productPanel.BackImageUrl = "../App_Themes/emmaharris/images/frame2.gif";
break;
case 2:
productPanel.BackImageUrl = "../App_Themes/emmaharris/images/frame3.gif";
break;
case 3:
productPanel.BackImageUrl = "../App_Themes/emmaharris/images/frame4.gif";
break;
}
}
// End of new code to switch background images
}
T
Upvotes: 0
Views: 2343
Reputation: 38385
Sometimes, Random isn't really Random...
Jon Skeet has a good article on the topic: Why am I getting the same numbers out of Random time and time again?
To quote directly what Jon had told me one time:
A pseudo-random number generator (like System.Random) isn't actually random - it will always produce the same sequence of results when initialised with the same data. The data that's used for initialisation is a number called the seed.
The basic problem is that when you create a new instance of Random using the parameterless constructor (as we're doing here) it uses a seed taken from "the current time". The computer's idea of "the current time" may only change once every 15ms (which is an eternity in computing) - so if you create several new instances of Random in quick succession, they will all have the same seed.
What you usually want (assuming you don't care about being able to reproduce exact results, and you don't need a cryptographically secure random number generator) is to have a single Random used throughout your program, initialised the first time it's used. That sounds like you could just use a static field somewhere (exposed as a property) - basically a singleton. Unfortunately System.Random isn't thread-safe - if you call it from two different threads, you could get problems (including getting the same sequence of numbers in both threads).
This is why I created StaticRandom in my little utilities toolbox - it's basically a thread-safe way of getting random numbers, using a single instance of Random and a lock. See http://www.yoda.arachsys.com/csharp/miscutil/usage/staticrandom.html for a quick example, and http://pobox.com/~skeet/csharp/miscutil for the library itself.
Jon Skeet's Misc Utility Random Generator
using System;
namespace MiscUtil
{
/// <summary>
/// Thread-safe equivalent of System.Random, using just static methods.
/// If all you want is a source of random numbers, this is an easy class to
/// use. If you need to specify your own seeds (eg for reproducible sequences
/// of numbers), use System.Random.
/// </summary>
public static class StaticRandom
{
static Random random = new Random();
static object myLock = new object();
/// <summary>
/// Returns a nonnegative random number.
/// </summary>
/// <returns>A 32-bit signed integer greater than or equal to zero and less than Int32.MaxValue.</returns>
public static int Next()
{
lock (myLock)
{
return random.Next();
}
}
/// <summary>
/// Returns a nonnegative random number less than the specified maximum.
/// </summary>
/// <returns>
/// A 32-bit signed integer greater than or equal to zero, and less than maxValue;
/// that is, the range of return values includes zero but not maxValue.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">maxValue is less than zero.</exception>
public static int Next(int max)
{
lock (myLock)
{
return random.Next(max);
}
}
/// <summary>
/// Returns a random number within a specified range.
/// </summary>
/// <param name="min">The inclusive lower bound of the random number returned. </param>
/// <param name="max">
/// The exclusive upper bound of the random number returned.
/// maxValue must be greater than or equal to minValue.
/// </param>
/// <returns>
/// A 32-bit signed integer greater than or equal to minValue and less than maxValue;
/// that is, the range of return values includes minValue but not maxValue.
/// If minValue equals maxValue, minValue is returned.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">minValue is greater than maxValue.</exception>
public static int Next(int min, int max)
{
lock (myLock)
{
return random.Next(min, max);
}
}
/// <summary>
/// Returns a random number between 0.0 and 1.0.
/// </summary>
/// <returns>A double-precision floating point number greater than or equal to 0.0, and less than 1.0.</returns>
public static double NextDouble()
{
lock (myLock)
{
return random.NextDouble();
}
}
/// <summary>
/// Fills the elements of a specified array of bytes with random numbers.
/// </summary>
/// <param name="buffer">An array of bytes to contain random numbers.</param>
/// <exception cref="ArgumentNullException">buffer is a null reference (Nothing in Visual Basic).</exception>
public static void NextBytes(byte[] buffer)
{
lock (myLock)
{
random.NextBytes(buffer);
}
}
}
}
Upvotes: 1
Reputation: 13210
I wonder if you have some level of caching operating on the panel which is causing it to not run through the server side processing in production mode.
Upvotes: 0
Reputation: 1316
Are you sure your page isn't cached? Do a view source on page.
Oh and there should be some function like urand or srand to make random more random.
Upvotes: 0