我已经围绕 Microsoft Office Document Imaging COM API 编写了一个 OCR 包装器库,并且在本地运行的控制台应用程序中,它在每次测试中都能完美运行。
遗憾的是,当我们尝试将其与在 IIS6 下作为 ASP.Net Web 应用程序运行的 WCF 服务集成时,事情开始变得糟糕。我们在尝试释放 MODI COM 对象时遇到了问题,网络上有很多示例可以帮助我们。
但是,问题仍然存在。如果我重新启动 IIS,并重新部署 Web 应用程序,前几次 OCR 尝试效果很好。如果我将其保留 30 分钟左右,然后执行另一个请求,我会收到如下服务器故障错误:
The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT)): at MODI.DocumentClass.Create(String 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();
}
}
然后,我在 using block 内实例化 ImageReader 的实例(退出时将调用 IDisposable.Dispose)
调用 Marshal.FinalReleaseComObject 应该指示 CLR 释放 COM 对象,因此我不知道是什么导致了我们所遇到的症状。
就其值(value)而言,在 IIS 之外运行此代码(例如在控制台应用程序中),一切似乎都是无懈可击的。每次都有效。
任何帮助我诊断和解决这个问题的提示都将是一个巨大的帮助,我会疯狂地投票! ;-)
谢谢!
最佳答案
您是否考虑过进程外托管应用的 OCR 部分。
拥有服务可以为您带来巨大的灵 active :
- 您可以为 Web 应用程序定义一个简单的端点,并通过远程处理或 WCF 访问它。
- 如果东西是梨形的,并且库都是闪避的,那么您可以让该服务在每次需要执行 OCR 时启动一个单独的进程。这为您提供了极大的安全性,但会产生少量的额外费用。我认为OCR 比启动流程要昂贵得多。
- 您可以保留 COM 对象的实例,如果内存开始泄漏,您可以自行重新启动而不影响网站(如果您小心的话)。
我个人过去发现 COM 互操作 + IIS = 悲伤。
关于asp.net - 如何在 ASP.Net Web 应用程序中使用 MODI?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1344510/