c# - 为什么这个方法对不同的用户吐出相同的结果

标签 c# asp.net random itext

所以我有生成条形码和带有该条形码的标签的方法。我们注意到,当多个用户同时生成条形码时,他们都将获得相同的文件。我正在使用 ASP.NET,我在内部服务器上托管应用程序和文件。

public void trickylabel(string fnsku, string title)
{
    Random random = new Random();
    int randomNumber = random.Next(0, 100000);

    //Set barcode properties...

    code.parse(fnsku); // Text

    BCGDrawing drawing = new BCGDrawing(this.Server.MapPath("~") + "image"+ randomNumber.ToString() +".png", color_white);
    drawing.setBarcode(code);
    drawing.draw();

    // Draw (or save) the image into PNG format.
    Response.ContentType = "image/png";
    drawing.finish(ImageFormat.Png);

    Document doc = new Document(new iTextSharp.text.Rectangle(200f, 75f), 20F, 10F, 10F, 1F);
    PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(Request.PhysicalApplicationPath +
        "\\"+randomNumber.ToString()+".pdf", FileMode.Create));

    doc.Open();

    iTextSharp.text.Image png = iTextSharp.text.Image.GetInstance(this.Server.MapPath("~") + "image" + randomNumber.ToString() +".png");

    doc.Add(png);

    //Sets pdf properties...

    doc.Add(new Paragraph(title, times));
    PdfAction action = new PdfAction(PdfAction.PRINTDIALOG);
    writer.SetOpenAction(action);
    doc.Close();

    Response.ContentType = "application/pdf";
    Response.AppendHeader("Content-Disposition", "attachment; filename=labels.pdf");
    Response.TransmitFile(Server.MapPath("~/"+randomNumber.ToString()+".pdf"));

}

最佳答案

问题出在这里:

Random random = new Random();
int randomNumber = random.Next(0, 100000);

Random 类生成伪随机序列,它基于一些称为种子的起始值。如果两个 Random 实例用相同的种子初始化,它们将产生相同的数字序列。

当使用无参数构造函数创建 Random 时,Seed 是从当前系统时间创建的。如果您运行一个创建 Random 类实例的循环,您会注意到 random.Next() 值每秒仅更改几次(每 16 毫秒一次)。

为避免这种情况,您应该重用已初始化的 Random 实例(但是,由于您使用的是 ASP.Net,因此您需要确保 random.Next() 的调用在线程安全的环境中执行方式)。然后您的访问者将在每次新的 random.Next(...) 调用中获得不同的值。

另外,Random 有一个允许手动设置初始种子值的构造函数。因此,您可以创建自己的算法来为您的用户创建独特的种子。

更新 线程安全的随机发生器实现。 在程序集加载时初始化。

用法:只需将 random.Next(0, 100000); 替换为 Randomizer.Next(0, 100000);

public static class Randomizer
{
    private static Random rnd;
    static Randomizer()
    {
        rnd = new Random();
        rndlock = new object();
    }

    private static object rndlock;
    public static int Next(int minValue, int maxValue)
    {
        lock(rndlock)
        {
            return rnd.Next(minValue, maxValue);
        }
    }
}

更新 关于线程安全和不可预测的结果

如上所述,Random 生成伪随机序列。这意味着此序列中的每个 int 数字都有已知的前一个和下一个数字。这意味着在调用一定次数后,这些号码将开始重复。 Random.Next() 算法旨在最大化此序列中唯一项的数量。

那么,在这种情况下,“不可预测”是什么意思?当多个线程同时使用相同的变量时,算法的逻辑就会被破坏。在最好的情况下,这会使相同数字的序列更频繁地出现。在最坏的情况下 Random.Next() starts to produce zero values on each call没有任何恢复的机会。

关于 System.Random 的更多有用信息 MSDN .

关于c# - 为什么这个方法对不同的用户吐出相同的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7337210/

相关文章:

c# - 如何获得枚举自定义值?

c# - 在javascript中访问C#变量

c# - 为什么 ObjectDataSource 中的 UpdateMethod 只接收来自 DetailsView 中可见控件的属性值?

java - 生成可验证的随机数 - Java

c# - 如何在 .net 4 Chart 中更改字体颜色

C#:泛型方法的 Func<T, TResult>

c# - 如何获取 Combobox.Datasource 到字典?

c# - 在负载平衡环境中丢弃服务器

python - 从 Pygame Sprite Collision 生成单个随机数,目前生成多个随机数

random - 从数组或列表中随机选取元素