题
我已经写了周围的微软Office文档成像COM API的OCR包装库,并在一个控制台应用程序在本地运行,它完美的作品,每测试。
不幸的是,事情开始变得糟糕,当我们试图将其与WCF服务运行作为一个ASP.Net Web应用程序,IIS6下整合。我们有问题,周围试图腾出MODI COM对象,并有大量的可以帮助我们在网络上的例子。
然而,问题仍然存在。如果我重新启动IIS,并做web应用程序的部署新鲜,前几OCR尝试工作的伟大。如果我离开它30分钟左右,然后做另一个请求,我得到的服务器故障的错误是这样的:
在服务器引发异常。 (从HRESULT异常:0x80010105(RPC_E_SERVERFAULT)):在MODI.DocumentClass.Create(字符串的FileOpen)
从上,每个请求将失败做OCR,直到我重置IIS,并且循环再次开始。这一点
我们运行在它自己的应用程序池这个应用程序,并在具有本地管理员权限的身份运行。
更新:这个问题可以通过执行OCR东西了过程来解决。看来好像MODI库不使用托管代码打得好,当谈到自己后清理,因此产生新的流程,每个OCR请求我的情况运行良好。
下面是执行OCR功能:
public class ImageReader : IDisposable
{
private MODI.Document _document;
private MODI.Images _images;
private MODI.Image _image;
private MODI.Layout _layout;
private ManualResetEvent _completedOCR = new ManualResetEvent(false);
// SNIP - Code removed for clarity
private string PerformMODI(string fileName)
{
_document = new MODI.Document();
_document.OnOCRProgress += new MODI._IDocumentEvents_OnOCRProgressEventHandler(_document_OnOCRProgress);
_document.Create(fileName);
_document.OCR(MODI.MiLANGUAGES.miLANG_ENGLISH, true, true);
_completedOCR.WaitOne(5000);
_document.Save();
_images = _document.Images;
_image = (MODI.Image)_images[0];
_layout = _image.Layout;
string text = _layout.Text;
_document.Close(false);
return text;
}
void _document_OnOCRProgress(int Progress, ref bool Cancel)
{
if (Progress == 100)
{
_completedOCR.Set();
}
}
private static void SetComObjectToNull(params object[] objects)
{
for (int i = 0; i < objects.Length; i++)
{
object o = objects[i];
if (o != null)
{
Marshal.FinalReleaseComObject(o);
o = null;
}
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public void Dispose()
{
SetComObjectToNull(_layout, _image, _images, _document);
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
我然后实例化一个使用块内ImageReader的实例(其将调用IDisposable.Dispose上出口)
调用Marshal.FinalReleaseComObject应指示CLR释放COM对象,所以我不知所措弄清楚什么是导致我们出现上述症状。
有关它的价值,运行IIS以外的代码,比如在一个控制台应用程序,一切似乎防弹。它屡试不爽。
这是帮我诊断和解决这个问题将是一个巨大的帮助,我会给予好评像疯了似的任何提示! ; - )
谢谢!
解决方案
你有没有想过你的托管应用程序的OCR部分的外的过程的。
有一个服务可以给你吨的灵活性:
- 您可以定义为Web应用程序一个简单的终点,并通过远程处理或WCF访问它。
- 如果东西是梨形状和图书馆是所有道奇,你可以有服务推出的每一个需要进行OCR时单独的进程。这给你极致的安全性,但涉及一个小的额外费用。我假设的 OCR是远比旋转起来的过程更昂贵的即可。
- 您可以保留一个实例周围的COM对象的,如果内存泄漏开始,你可以重新开始自己,而不会影响网站(如果你很小心)。 醇>
我个人在过去发现COM互操作+ IIS =悲伤。
其他提示
MODI是非常靠不住的,当涉及到摆脱自身,在IIS中运行特别。根据我的经验,我发现,虽然它减缓都记录下来,只有这样,才能摆脱这些错误的是你的所以GC.Collect()调用后添加GC.WaitForPendingFinalizers()。如果你有兴趣,我写了一个这篇文章。
您可以复制的问题,在一个小型控制台应用程序?也许离开它睡了30分钟,回来了吗?
为了解决这样的事情最佳方法是将其完全分离下来。我很想看看它是如何工作。
我只好一个星期前处理这个错误,并测试了一些解决方案在这里发出后,我终于解决了这个问题。我做到了,我会在这里解释。
从HRESULT异常:在我的情况下,我有一个窗口服务乳宁和处理文档从一个文件夹中,当存在多于20个文档,引发错误出现问题。0x80010105(RPC_E_SERVERFAULT)
在我的代码我是每次我检测该文件夹中的文档调用一个方法,我让MODI文档的实例(MODI.Document _document =新MODI.Document();)和i处理该文件,并且是什么原因导致的错误!!
解决方案是只有一个全球MODI.Document的实例,并处理所有的文件白衣它,这样我只有一个实例乳宁为我服务的所有时间。
我希望这将有助于那些谁是面临同样的问题。