所以我有生成条形码和标签的方法。我们注意到,当多个用户同时生成条形码时,它们都将获得相同的文件。我正在使用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"));
}
答案 0 :(得分:4)
问题在于:
Random random = new Random();
int randomNumber = random.Next(0, 100000);
Random类生成伪随机序列,该序列基于一些起始值,称为Seed。如果用相同的种子初始化两个Random实例,它们将产生相等的数字序列。
使用无参数构造函数创建Random时,将从当前系统时间创建Seed。如果你运行一个创建Random类实例的循环,你会发现random.Next()值每秒只改变几次(每16ms一次)。
为了避免这种情况,你应该重用初始化的Random实例(但是,因为你使用 ASP.Net ,你需要确保在线程安全中执行random.Next()的调用。办法)。然后,您的访问者将获得不同的值,每个新的random.Next(...)调用。
或者,Random有一个构造函数,允许手动设置初始种子值。因此,您可以创建自己的算法,为您的用户创建独特的种子。
UPDATE 线程安全的Randomizer实现。 在程序集加载时初始化。
用法:只需将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没有任何机会恢复。
有关MSDN上的System.Random的更多有用信息。
答案 1 :(得分:1)
或者只使用NewGuid Method
答案 2 :(得分:0)
如果请求同时开始,则生成的随机数可能彼此相同。在没有提供种子值的情况下,Random构造函数根据系统时钟获取其种子,因此两个实例可能产生相同的随机值集合(这些随机值不是随机的,它们是伪随机的)。
此处的文档 - http://msdn.microsoft.com/en-us/library/system.random.aspx
尝试将Random实例设为类的静态成员,并让您的方法只调用该成员上的.Next。
答案 3 :(得分:0)
您需要将pdf保存到磁盘吗?
我建议将png图像和pdf文档保存到MemoryStream
。
这也可能会带来更好的性能,因为磁盘访问量更少。
public void trickylabel(string fnsku, string title)
{
//Set barcode properties...
code.parse(fnsku); // Text
BCGDrawing drawing = new BCGDrawing(color_white);
drawing.setBarcode(code);
drawing.draw();
// Draw (or save) the image into PNG format.
using (var imageStream = new MemoryStream())
{
drawing.finish(ImageFormat.Png, imageStream);
using (var result = new MemoryStream())
{
Document doc = new Document(new iTextSharp.text.Rectangle(200f, 75f), 20F, 10F, 10F, 1F);
PdfWriter writer = PdfWriter.GetInstance(doc, result);
doc.Open();
var png = iTextSharp.text.Image.GetInstance(System.Drawing.Image.FromStream(imageStream), ImageFormat.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.BinaryWrite(result.ToArray());
}
}
}