Mario
Mario

Reputation: 179

Wordapp not closing in Thread or Parallel process

the code below normally works and word is opened and closed after saving a docx/doc to pdf however when using the following code in a thread or Parallel for loop it does not, any have any ideas? I have provided all the code below.

this is the code when used in a function works fine.

     wordApp = new Microsoft.Office.Interop.Word.Application();
        Microsoft.Office.Interop.Word.Document wordDocument = wordApp.Documents.Open(sourceFile, false);
        wordDocument.ExportAsFixedFormat(destFile, WdExportFormat.wdExportFormatPDF);
        object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
        object originalFormat = Microsoft.Office.Interop.Word.WdOriginalFormat.wdOriginalDocumentFormat;
        object routeDocument = false;


        if (wordDocument != null)
            ((_Document)wordDocument).Close(ref saveOption, ref originalFormat, ref routeDocument);

        if (wordApp != null)
            ((_Application)wordApp).Quit(ref saveOption, ref originalFormat, ref routeDocument);

        wordDocument = null;
        wordApp = null;

Below is the Parallel.For code which i tried to call the code above:

   Parallel.For(1, Int32.Parse(iNrOfThreads.Text), new ParallelOptions { MaxDegreeOfParallelism = Int32.Parse(iNrOfThreads.Text) }, i =>                 
            {
                fileName = fileNameLarge + i.ToString() + ".doc";
                fileName2 = fileNameLarge + i.ToString() + ".pdf";
                string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
                string destFile = System.IO.Path.Combine(targetPath, fileName2);

                GeneratePDFWithProgressWithCreate(sourceFile, destFile);

            });

and below is the for loop which generates thread which i tried to call the code above:

    for (int i = 1; i <= Int32.Parse(iNrOfThreads.Text); i++)
            {
                //fileName2 = fileNameSmall + i.ToString() + ".docx";
                fileName = fileNameLarge + i.ToString() + ".doc";
                fileName2 = fileNameLarge + i.ToString() + ".pdf";
                string sourceFile = System.IO.Path.Combine(sourcePath, fileName);
                string destFile = System.IO.Path.Combine(targetPath, fileName2);

                // To copy a file to another location and 
                // overwrite the destination file if it already exists.
                //System.IO.File.Copy(sourceFile, destFile, true);

                //Thread thread = new Thread(() => GeneratePDFWithProgress(sourceFile, destFile + ".pdf"));
                Thread thread = new Thread(() => GeneratePDFWithProgressWithCreate(sourceFile, destFile));
                thread.Name = "Thread" + i.ToString();
                thread.IsBackground = true;
                thread.SetApartmentState(ApartmentState.MTA);
                thread.Start();              
            } 

Upvotes: 1

Views: 1330

Answers (1)

Mario
Mario

Reputation: 179

I solved it by declaring the variable local

from the original code

    wordApp = new Microsoft.Office.Interop.Word.Application();

I changed it to

    Microsoft.Office.Interop.Word.Application wordAppPrivate = new Microsoft.Office.Interop.Word.Application();

So now it is local to the function here is the complete code for the function called with the thread i create

    void GeneratePDFWithProgressWithCreate(string wordFilename, string pdfFilename)        
    {       
            // Update Progress bar to see start of threads         
            UpdateProgress();
            // Setup Word Application
            Microsoft.Office.Interop.Word.Application wordAppPrivate = new Microsoft.Office.Interop.Word.Application();
            Microsoft.Office.Interop.Word.Document wordDocument = wordAppPrivate.Documents.Open(wordFilename, false);
            wordDocument.ExportAsFixedFormat(pdfFilename, WdExportFormat.wdExportFormatPDF);
            object saveOption = Microsoft.Office.Interop.Word.WdSaveOptions.wdDoNotSaveChanges;
            object originalFormat = Microsoft.Office.Interop.Word.WdOriginalFormat.wdOriginalDocumentFormat;
            object routeDocument = false;

            if (wordDocument != null) 
                ((_Document)wordDocument).Close(ref saveOption, ref originalFormat, ref routeDocument);
            if (wordAppPrivate != null)
                ((_Application)wordAppPrivate).Quit(ref saveOption, ref originalFormat, ref routeDocument);

            if (wordDocument != null)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(wordDocument);

            if (wordAppPrivate != null)
                System.Runtime.InteropServices.Marshal.ReleaseComObject(wordAppPrivate);

            wordDocument = null;
            wordAppPrivate = null;
            //GC.Collect(); // force final cleanup!

            // Update progress bar to see finishing the conversion
            UpdateProgress();               
        //}
    }

I hope this will help others who have similar problems!

Upvotes: 1

Related Questions