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.
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.
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); flexCelPdfExport1.BeginExport(Pdf); flexCelPdfExport1.ExportSheet(); flexCelPdfExport1.EndExport(); Pdf.Close();
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); flexCelPdfExport1.BeginExport(Pdf); flexCelPdfExport1.ExportSheet(); flexCelPdfExport1.EndExport(); Pdf.Close();
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.