什么污染了这个开关声明?

时间:2017-07-24 09:56:21

标签: c# multithreading windows-services task-parallel-library aspose

我有一个正在执行以下操作的系统,

  • 将文档上传到SharePoint
  • 事件接收器将向DB添加作业,在文档转换目录中创建作业文件夹
  • 目录观察程序将触发文档转换窗口服务
  • Windows服务将从DB(使用主线程)获得10个作业批次
  • 启动时Windows服务根据处理器核心创建X个线程(使用Parallel For)
  • 然后为每个db作业创建具有超时的工作线程(这与并行的线程不同)
  • 它继续......
  • 在工作线程中转换...时我们正在调用ActiveDirectory,登录到DB(读取,写入)并将文档上载回SharePoint

我设法打破它......如果我上传受密码保护的文件......并且在上传powerpoint文档后不久,powerpoint文档会抛出密码错误的异常等。

但是如果两个文件之间的差距甚至是60秒,那么一切正常,这意味着powerpoint文档会转换为PDF。

以下是代码,但我不得不修剪不必要的部分,

以下是事物开始的主要课程,

 Parallel.For(0, noOfThreadsToRunOnPDFServer, new ParallelOptions { MaxDegreeOfParallelism = noOfThreadsToRunOnPDFServer },
    i =>
    {
        this.docConvService.ProcessDocuments(i);
    });

然后转换发生在这里......

using System;
using System.IO;
using System.Runtime.ExceptionServices;
using System.Threading;

namespace PDFService
{
    public class AsposePDFConverter : IPDFConverter
    {
        private IDocConversionSettings settings;
        private ExceptionDispatchInfo conversionException = null;
        public enum SupportedExtensions
        {
            Doc,
            Docx,
            Xls,
            Xlsx,
            Pdf,
            Pps,
            Ppsx,
            Ppt,
            Pptx,
            Txt,
            Html,
            Mhtml,
            Xhtml,
            Msg,
            Eml,
            Emlx,
            One,
            Vsd,
            Vsdx,
            Vss,
            Vssx
        }

        public AsposePDFConverter(IDocConversionSettings settings)
        {
            this.settings = settings;
        }

        private void SyncThreadStartWithTimeout(ThreadStart threadStart, TimeSpan timeout)
        {
            Thread workerThread = new Thread(threadStart);
            workerThread.Start();

            bool finished = workerThread.Join(timeout);
            if (!finished)
            {
                workerThread.Abort();
                throw new ConversionTimeoutException("PDF Conversion exceeded timeout value");
            }
        }

        public MemoryStream ConvertToPDF(string documentName, Stream docContent, double timeoutMS)
        {
            this.conversionException = null;

            MemoryStream outStream = null;
            MemoryStream inStream = new MemoryStream();
            docContent.CopyTo(inStream);
            inStream.Seek(0, SeekOrigin.Begin);

            SupportedExtensions documentExtension;
            string szExtension = Path.GetExtension(documentName).TrimStart('.');
            if (Enum.TryParse(szExtension, true, out documentExtension))
            {
                switch (documentExtension)
                {
                    case SupportedExtensions.Doc:
                    case SupportedExtensions.Docx:
                    case SupportedExtensions.Txt:
                    case SupportedExtensions.Html:
                    case SupportedExtensions.Mhtml:
                    case SupportedExtensions.Xhtml:
                        SyncThreadStartWithTimeout(
                                () => { outStream = ConvertWordsToPDF(inStream); },
                                TimeSpan.FromMilliseconds(timeoutMS));
                        break;
                    case SupportedExtensions.Pps:
                    case SupportedExtensions.Ppsx:
                    case SupportedExtensions.Ppt:
                    case SupportedExtensions.Pptx:
                        SyncThreadStartWithTimeout(
                                () => { outStream = ConvertSlidesToPDF(inStream); },
                                TimeSpan.FromMilliseconds(timeoutMS));
                        break;
                }

                // Conversion happens on sub-threads so they can time out, if they throw an exception, throw it from this thread
                if (this.conversionException != null)
                    this.conversionException.Throw();

                return outStream;
            }
            else
            {
                throw new FormatNotSupportedException("Document type is not supported");
            }
        }

        private MemoryStream ConvertWordsToPDF(Stream docContent)
        {
            try
            {
                Aspose.Words.License lic = new Aspose.Words.License();
                lic.SetLicense(this.settings.AsposeLicensePath);
                Aspose.Words.Document doc = new Aspose.Words.Document(docContent);

                MemoryStream stream = new MemoryStream();
                doc.Save(stream, Aspose.Words.SaveFormat.Pdf);
                return stream;
            }
            catch (Exception ex)
            {
                this.conversionException = ExceptionDispatchInfo.Capture(ex);
                return null;
            }
        }

        private MemoryStream ConvertSlidesToPDF(Stream docContent)
        {
            try
            { 
                Aspose.Slides.License lic = new Aspose.Slides.License();
                lic.SetLicense(this.settings.AsposeLicensePath);
                using (Aspose.Slides.Presentation presentation = new Aspose.Slides.Presentation(docContent))
                {
                    MemoryStream stream = new MemoryStream();
                    presentation.Save(stream, Aspose.Slides.Export.SaveFormat.Pdf);
                    return stream;
                }
            }
            catch (Exception ex)
            {
                this.conversionException = ExceptionDispatchInfo.Capture(ex);
                return null;
            }
        }

    }
}

错误是,

  

文档PDF转换期间出错。详细信息是:PDFConversionID:   6061,DocumentName:powerpoint.ppsx,WebURL:REMOVED,UploadedBy:   REMOVED,ConversionDuration:00:01:06.3072410

     

Aspose.Words.IncorrectPasswordException:文档密码是   不正确。在Aspose.Words.Document。 (Stream,LoadOptions)
  在Aspose.Words.Document。 (Stream,LoadOptions)at   DocumentPDFConversionService.AsposePDFConverter.ConvertWordsToPDF(流   docContent)in ...

正如你所看到的那样,有一些非常可疑的东西

1 个答案:

答案 0 :(得分:4)

您在多个线程中使用了相同的this.docConvService实例,因此您的conversionException属性可能是在您的其他文档正在处理时由受密码保护的文档编写的。您应该实例化AsposePDFConverter的新实例,或者更改返回异常的方式,例如:在ConvertToPDF返回的结果对象中,包含一个MemoryStream和你的错误。

每个请求的单独实例:

Parallel.For(0, noOfThreadsToRunOnPDFServer, new ParallelOptions { MaxDegreeOfParallelism = noOfThreadsToRunOnPDFServer },
    i =>
    {
        new AsposePdfConverter(settings).ProcessDocuments(i);
    });

返回结果对象:

 public ConversionResult ConvertToPDF(string documentName, Stream docContent, double timeoutMS)
{
    /** Your code **/
    return new ConversionResult() 
        {
        MemoryStream = memoryStream,
        ConversionException = conversionException
        };
}

class ConversionResult {
    MemoryStream MemoryStream {get;set;}
    ExceptionDispatchInfo ConversionException {get;set;}
}