我在Microsoft Office Document Imaging COM API周围编写了一个OCR包装器库,在本地运行的Console App中,每次测试都可以完美运行.
遗憾的是,当我们尝试将它与在IIS6下作为ASP.Net Web应用程序运行的WCF服务集成时,事情开始变得糟糕.我们在尝试释放MODI COM对象时遇到了问题,网上有很多帮助我们的例子.
但问题仍然存在.如果我重新启动IIS,并重新部署Web应用程序,那么前几次OCR尝试工作得很好.如果我离开它30分钟左右,然后再做另一个请求,我会收到服务器故障错误,如下所示:
服务器抛出异常.(来自HRESULT的异常:0x80010105(RPC_E_SERVERFAULT)):在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块中实例化一个ImageReader实例(在退出时会调用IDisposable.Dispose)
调用Marshal.FinalReleaseComObject应该指示CLR释放COM对象,因此我无法弄清楚导致我们症状的原因.
为了它的价值,在IIS之外运行这些代码,比如一个控制台应用程序,一切似乎都是防弹的.它每次都有效.
任何帮助我诊断和解决这个问题的提示都将是一个巨大的帮助,我会疯狂地投票!;-)
谢谢!