So I have method that generates a barcode and label with that barcode. We have noticed that when more than one user generate a barcode at the same time they will both get the same file. I am using ASP.NET and I am hosting the application and the file on the a in house server.
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"));
}
The problem is here:
The Random class generates pseudo-random sequence, that is based on some starting value, called Seed. If two Random instances are initialized with equal seeds they will produce equal number sequences.
When Random is created with parameterless constructor the Seed is created from current system time. If you ran a loop that creates instances of Random class you will notice that random.Next() value changes only several times per second (once per 16ms).
To avoid this you should reuse initialized Random instance (however, since you are using ASP.Net you will need to ensure that the calls of random.Next() are executed in a thread-safe way). Then your visitors will get different values each new random.Next(…) call.
Alternatively Random has a constructor that allows to set the initial Seed value manually. So, you can create your own algorithm of creating unique seeds for your users.
UPDATE Thread-safe Randomizer implementation.
Gets initialized on assembly load.
Usage: just replace
random.Next(0, 100000);toRandomizer.Next(0, 100000);UPDATE On thread safety and unpredictable results
As stated above, Random generates pseudo-random sequence. This means that each int number in this sequence has known previous and next numbers. This means that after a certain number of calls these numbers will start to repeat. The Random.Next() algorithm is designed to maximize number of unique items in this sequence.
So, what “unpredictable” means in this case? When several threads use the same variables simultaneously the logic of the algorithm becomes corrupted. In best scenario this makes sequences of same numbers occur more often. In worst scenario Random.Next() starts to produce zero values on each call without any chance to recover.
More useful information about System.Random on MSDN.