0

I'm trying to merge some PDF documents using a Parallel.For loop so that I can create multiple documents at once. 99+% it works fine (and works perfectly when MaxDegreeOfParallelism = 1) but I am getting an issue here when I merge multiple copies of the same PDF. transItem.DocumentList would contain all the documents and their merge fields like this:

DocID   Field     Value
1       LastName  Smith
2       Year      2015
2       Year      2016
2       Year      2017

Below is my code

var options = new ParallelOptions { MaxDegreeOfParallelism = -1 };

Parallel.ForEach(transItem.DocumentList, options, (docItem) =>
{
    //Get list of merge field for this document
    List<Document> fieldList = documentList.Where(x => x.document_id == docItem.document_id).ToList();

    //Get the extension (if any) and make it part of the bar code
    int extension = 0;

    if (GlobeTax.GlobeTax.IsNumeric(docItem.extension))
        extension = int.Parse(docItem.extension);

    docItem.bar_code = "01" + extension.ToString("00") + transItem.TransactionID.ToString("00000000") + docItem.document_id.ToString("0000");

    //Iterate through the field list and assign the values 
    foreach (Document docFieldItem in fieldList)
    {
        //Assign the value from the cobject containing the merge data.
        GetFieldValue(docFieldItem, boData, docItem.extension, emailInstructionsSB.ToString());

        docFieldItem.bar_code = docItem.bar_code;
    }

   pdfList[docItem.array_pos] = docManagerAPI.ProcessPDF(fieldList);

});

The result is that sometimes I get two document #2 with a year of 2016, none with 2015, and one with 2017. Sometimes the barcode value does not match the year on the document.

I'm pretty new to this and so may be making an obvious mistake. Does anything jump out at anyone?

Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
CarlGanz
  • 189
  • 11
  • 4
    What type is `pdfList`? Is it thread-safe? Use a [thread-safe](https://learn.microsoft.com/en-us/dotnet/standard/collections/thread-safe/) collection. – Peter Bons Dec 10 '18 at 13:15
  • Along with what @PeterBons asked, if you want to see if that is the culprit add a lock statement around the indexer to see if that fixes the issue and then you will have your answer (or not). `lock(pdfList) { pdfList[...... };` If that "solves" the issue then the problem is that this is not a thread safe collection and you must synchronize write access to it. Depending on what type this is you *might* be able to replace it with a thread safe type. – Igor Dec 10 '18 at 13:18
  • pdfList is an array of Syncfusion PDFLoadedDocuments objects. I replaced the array with a ConcurrentBag object but that had the same problem. lock(pdfList) on wither the array or the ConcurrentBag had no effect. What else could be wrong here? – CarlGanz Dec 10 '18 at 14:23
  • What is `GetFieldValue`. It says "Get" but the comment says it's assigning something. If you have multiple threads updating the same data then weird things are going to happen. When we have multithreading issues it tends to happen exactly as you are describing. It works the way we expect most of the time and then occasionally does something weird. It's important to assume that the iterations will not start or complete in any predictable sequence, even if they do some or most of the time. – Scott Hannen Dec 10 '18 at 14:37
  • GetFieldVAlue is a large swicth statementsthat does this: private static void GetFieldValue(Document docFieldItem, BOData boData, string extension, string emailInstructions) { CEncryption oDecryption = null; switch (docFieldItem.field_name) { case "txtContactDescr": docFieldItem.data_value = boData.contact_descr; break; It assigned the values in the data object to the collection containing the merge field names. Yes, AssignFieldValues() would be a better name! – CarlGanz Dec 10 '18 at 14:45
  • Given what's in the OP and what's not, it's difficult to visualize what's happening. But try to imagine what would happen (what is happening) if iterations of your parallel foreach loop don't occur in any particular sequence. That might help you to find the issue. – Scott Hannen Dec 10 '18 at 14:57

0 Answers0