所以我有生成条形码和带有该条形码的标签的方法。我们注意到,当多个用户同时生成条形码时,他们都将获得相同的文件。我正在使用 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/