如何在ASP.Net Web应用程序中使用MODI?

时间:2009-08-28 00:59:06

标签: asp.net ocr modi

我在Microsoft Office Document Imaging COM API周围编写了一个OCR包装器库,在本地运行的Console App中,每次测试都可以完美运行。

可悲的是,当我们尝试将其与作为ASP.Net Web应用程序运行的WCF服务集成在IIS6下时,情况开始恶化。我们在尝试释放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之外运行这些代码,比如一个控制台应用程序,一切似乎都是防弹的。它每次都有效。

任何帮助我诊断和解决这个问题的提示都将是一个巨大的帮助,我会疯狂地投票! ; - )

谢谢!

4 个答案:

答案 0 :(得分:4)

您是否考虑过托管应用的OCR部分进程外

提供服务可以为您提供大量的灵活性:

  1. 您可以为Web应用程序定义一个简单的端点,并通过远程处理或WCF访问它。
  2. 如果东西是梨形并且库都是闪避的,那么每次需要执行OCR时,您都可以让服务启动一个单独的进程。这为您提供极高的安全性,但需要额外的费用。我认为 OCR比启动流程要贵得多
  3. 您可以保留COM对象的实例,如果内存开始泄漏,您可以自行重启而不会影响网站(如果您小心)。
  4. 我个人在过去发现了COM互操作+ IIS =悲伤。

答案 1 :(得分:1)

MODI在摆脱自身方面非常不稳定,特别是在IIS中运行。根据我的经验,我发现尽管它减慢了所有内容,但摆脱这些错误的唯一方法是在GC.Collect()调用之后添加GC.WaitForPendingFinalizers()。如果您有兴趣,我写了article关于此事。

答案 2 :(得分:1)

您可以在小型控制台应用程序中复制问题吗?也许让它睡30分钟然后回到它?

解决这类问题的最佳方法是完全隔离它。我有兴趣看看它是如何工作的。

答案 3 :(得分:1)

一周前我不得不处理这个错误,在测试了一些解决方案之后,我终于解决了这个问题。我将在这里解释我是如何做到的。

在我的情况下,我有一个Windows服务运行和处理文件夹中的文件,当有超过20个文件时,会出现问题,抛出错误:来自HRESULT的异常:0x80010105(RPC_E_SERVERFAULT)。

在我的代码中,我每次在文件夹中检测到文档时都调用一个方法,我创建一个MODI文档的实例(MODI.Document _document = new MODI.Document();)并且我处理该文件,并且是导致错误的原因!!

解决方案是只有一个MODI.Document的全局实例,并处理所有文件,这样我只有一个实例为我的服务一直运行。

我希望这能帮助那些面临同样问题的人。