0

我正在尝试获取一个随机选择的背景图像(从 4 个图像中选择)以显示为 asp.net 面板的背景图像。

我遇到的问题是代码在调试模式下单步执行代码时有效。一旦你在网站上运行代码而不进行调试,所有的图像都是一样的。就好像随机数没有足够快地被拾取一样。

用户控件位于数据列表中。

用户控件是这样的:

<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>

后面的代码是这样的:

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

    }

4

3 回答 3

1

有时,随机并不是真的随机......

Jon Skeet 有一篇关于这个主题的好文章:为什么我一次又一次地从 Random 中得到相同的数字?

直接引用乔恩曾经告诉我的话:

伪随机数生成器(如 System.Random)实际上并不是随机的——当使用相同的数据初始化时,它总是会产生相同的结果序列。用于初始化的数据是一个称为种子的数字。

基本问题是,当您使用无参数构造函数(正如我们在这里所做的那样)创建 Random 的新实例时,它使用从“当前时间”获取的种子。计算机关于“当前时间”的概念可能每 15 毫秒才会改变一次(这在计算中是永恒的)——因此,如果您连续快速创建几个新的 Random 实例,它们都将具有相同的种子。

您通常想要的(假设您不关心能够重现精确结果,并且您不需要加密安全的随机数生成器)是在整个程序中使用单个 Random,并在第一次使用时进行初始化。听起来您可以在某处使用静态字段(作为属性公开)-基本上是单例。不幸的是 System.Random 不是线程安全的——如果你从两个不同的线程调用它,你可能会遇到问题(包括在两个线程中获得相同的数字序列)。

这就是我在我的小实用工具箱中创建 StaticRandom 的原因——它基本上是一种获取随机数的线程安全方式,使用 Random 的单个实例和一个锁。 有关快速示例, 请参阅 http://www.yoda.arachsys.com/csharp/miscutil/usage/staticrandom.html ,有关库本身,请参阅http://pobox.com/~skeet/csharp/miscutil

Jon Skeet 的 Misc 实用程序随机生成器

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);
            }
        }
    }
}
于 2009-10-12T20:40:25.623 回答
0

你确定你的页面没有被缓存?在页面上查看源代码。

哦,应该有一些像 urand 或 srand 这样的函数来使 random 更加随机。

于 2009-10-12T20:36:52.667 回答
0

我想知道您是否在面板上运行了某种级别的缓存,这导致它无法在生产模式下通过服务器端处理运行。

于 2009-10-12T20:38:12.553 回答