Duplicate contents of PDF in different files

We have noticed an issue when creating a PDF using Flexcel on our web app.  Here is what happens:

1. Two users are using the website at the same time and initiate the creation of a PDF at nearly the same time.

2. We fill a Flexcel Excel structure which is then converted to a PDF file within each session (data is different for each session)

What we find is that when two different sessions create a PDF at nearly the same time, two PDF files are created with different file names but the contents of the two are the same.

We are using Flexcel V5.3.0

Any idea of why this is happening?  Also, any suggestion for resolving this issue?




Even when FlexCel 5.3 is quite old and it could always be a bug that has been fixed in the meantime, I am pretty confident this is not a bug in the FlexCel side. FlexCel has been designed from the ground up to work in parallel, and it is constantly tested creating thousands of pdf files in parallel. We also have many customers using it in high-demand situations creating dozens of files in parallel, and have never seen a problem reported.

Our tests for example uncovered a bug in System.IO.Packaging (what we were using before to create xlsx files) that would cause a freeze when 2 threads try to create a file at the same time and one file is bigger than 10mb. (see http://www.tmssoftware.biz/flexcel/doc/net/about/whatsnew.html#new-on-v-5700---march-2012 )

While this was fixed in a version a little newer than yours, the problem was that the app would freeze, not that the contests would be the same. This kind of bug would have been found much sooner than 5.3.

Now, about why it happens, it is hard to say without looking at your code, but my guess is that somehow you are sharing  XlsFile objects and both FlexCelPDFExport objects are using the same. Or somehow, you are filling both objects with the same data because the database connections aren't threadsafe.

You can also search for "LightClone" in your app: While this method was introduced a little later than 5.3, if you don't use it correctly it could create a situation like this.

Thank you for the incredibly prompt and detailed response!  I will use your suggestions to figure out what we are doing to cause this issue.

We were not setting a unique name when creating the Excel File. 

ExcelFile Xls = new XlsFile();

Would we be then writing to the same excel file in concurrent sessions as the default Excel file name would be the same for both sessions?

There is no default filename in FlexCel, you give the file a name when you call "Save"

When you cell xls.Save(...) is there a way that both filenames could be the same?
The other thing is when you call SetCellValue(...), maybe the values where you read can be the same when you have more than one thread?
We are not saving the excel file.  We are doing the following:

public FlexCel.Render.FlexCelPdfExport flexCelPdfExport1 = new FlexCelPdfExport();

then in the method:

flexCelPdfExport1.Workbook = Xls;
flexCelPdfExport1.Workbook.ActiveSheet = 1;

FileStream Pdf = new FileStream(outputFile, FileMode.Create);

Perhaps that it the issue?

No, that's fine. There is no need to Save the Excel file.

Now, looking at that code, where is flexCelPdfExport1 defined?  Maybe it is a global variable or a compoent?

If should be defined as:

using (FlexCelPdfExport1 = new FlexCelPdfExport())
   flexCelPdfExport1.Workbook = Xls;
flexCelPdfExport1.Workbook.ActiveSheet = 1;

FileStream Pdf = new FileStream(outputFile, FileMode.Create);

Yes, we defined it as a global variable within its class.  We can certainly rewrite it as you suggest.

Would you mind explaining why this would be an issue if it is defined as a global variable across sessions? I just want to make sure we resolve the issue and understand why.


Well, it depends if the class itself is shared with other threads or not.

But if you have thread1 and thread2 both using the same global FlexCelPDFExport object it will cause problems.

Anyway, even if this is not the cause, having the FlexCelPDFExport local is a better practice, since you can be sure it is not accidentally shared with other objects. It will also release the memory once the using{} ends, while if it is a global variable, it will keep using the memory.
Got it.

Thank you!!!