是什么污染了这个 switch 语句?
What is contaminating this switch statement?
我有一个正在执行以下操作的系统,
- 将文档上传到 SharePoint
- 事件接收器将作业添加到数据库,在文档转换目录中为作业创建一个文件夹
- 目录观察器将触发文档转换 windows 服务
- Windows 服务将从数据库中获取一批 10 个作业(使用主线程)
- 启动时Windows 服务根据处理器核心创建 X 个线程(使用 Parallel For)
- 然后为每个数据库作业创建超时的工作线程(这与并行线程不同)
- 它继续...
- 哦,在工作线程中转换...我们正在调用 ActiveDirectory,记录到数据库(读、写)并将文档上传回 SharePoint
我设法破解了它...如果我上传受密码保护的文档...并且在上传 powerpoint 文档后不久,powerpoint 文档会抛出密码不正确的异常等。
但是如果两个文档之间有 60 秒的间隔,一切正常,这意味着 powerpoint 文档确实可以转换为 PDF。
以下是代码,但我不得不 trim 从中删除不必要的部分,
这里是主要的class事情开始的地方,
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;
}
}
}
}
错误是,
Error during Document PDF Conversion. Details are: PDFConversionID:
6061, DocumentName: powerpoint.ppsx, WebURL: REMOVED, UploadedBy:
REMOVED, ConversionDuration: 00:01:06.3072410
Aspose.Words.IncorrectPasswordException: The document password is
incorrect. at Aspose.Words.Document. (Stream , LoadOptions )
at Aspose.Words.Document. (Stream , LoadOptions ) at
DocumentPDFConversionService.AsposePDFConverter.ConvertWordsToPDF(Stream
docContent) in...
如您所见,发生了一些非常可疑的事情
您在多个线程中使用了 this.docConvService 的同一个实例,因此您的 conversionException 属性 可能是在处理其他文档时由受密码保护的文档编写的。您应该实例化 AsposePDFConverter 的新实例,或更改 return 异常的方式,例如在由 ConvertToPDF 编辑的结果对象 return 中,其中包含 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;}
}
我有一个正在执行以下操作的系统,
- 将文档上传到 SharePoint
- 事件接收器将作业添加到数据库,在文档转换目录中为作业创建一个文件夹
- 目录观察器将触发文档转换 windows 服务
- Windows 服务将从数据库中获取一批 10 个作业(使用主线程)
- 启动时Windows 服务根据处理器核心创建 X 个线程(使用 Parallel For)
- 然后为每个数据库作业创建超时的工作线程(这与并行线程不同)
- 它继续...
- 哦,在工作线程中转换...我们正在调用 ActiveDirectory,记录到数据库(读、写)并将文档上传回 SharePoint
我设法破解了它...如果我上传受密码保护的文档...并且在上传 powerpoint 文档后不久,powerpoint 文档会抛出密码不正确的异常等。
但是如果两个文档之间有 60 秒的间隔,一切正常,这意味着 powerpoint 文档确实可以转换为 PDF。
以下是代码,但我不得不 trim 从中删除不必要的部分,
这里是主要的class事情开始的地方,
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;
}
}
}
}
错误是,
Error during Document PDF Conversion. Details are: PDFConversionID: 6061, DocumentName: powerpoint.ppsx, WebURL: REMOVED, UploadedBy: REMOVED, ConversionDuration: 00:01:06.3072410
Aspose.Words.IncorrectPasswordException: The document password is incorrect. at Aspose.Words.Document. (Stream , LoadOptions )
at Aspose.Words.Document. (Stream , LoadOptions ) at DocumentPDFConversionService.AsposePDFConverter.ConvertWordsToPDF(Stream docContent) in...
如您所见,发生了一些非常可疑的事情
您在多个线程中使用了 this.docConvService 的同一个实例,因此您的 conversionException 属性 可能是在处理其他文档时由受密码保护的文档编写的。您应该实例化 AsposePDFConverter 的新实例,或更改 return 异常的方式,例如在由 ConvertToPDF 编辑的结果对象 return 中,其中包含 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;}
}