Pregunta

He escrito una biblioteca envoltorio OCR alrededor de la API de Microsoft Office Document Imaging COM, y en una aplicación de consola que se ejecutan localmente, que funciona a la perfección, con cada prueba.

Por desgracia, las cosas empiezan a ir mal cuando se intenta integrar con un servicio WCF se ejecuta como una aplicación Web ASP.Net, bajo IIS6. Tuvimos problemas por ahí tratando de liberar los objetos COM MODI, y había un montón de ejemplos en la web que nos ayudó.

Sin embargo, sigue habiendo problemas. Si recomienzo IIS, y hacer un nuevo despliegue de la aplicación web, los primeros intentos de OCR funcionan muy bien. Si lo dejo durante 30 minutos más o menos, y luego hacer otra petición, consigo errores de servidor de fallo como este:

  

El servidor inició una excepción. (Excepción de HRESULT: 0x80010105 (RPC_E_SERVERFAULT)): en MODI.DocumentClass.Create (String FileOpen)

A partir de ahora, cada solicitud dejará de hacer el OCR, hasta que restablecer IIS, y el ciclo comienza de nuevo.

ejecutar esta aplicación en su propio grupo de aplicaciones, y se ejecuta bajo una identidad con derechos de administrador local.

ACTUALIZACIÓN: Este problema se puede resolver haciendo las cosas OCR fuera del proceso. Parece como si la biblioteca MODI no juega bien con código administrado, cuando se trata de limpiar después de sí mismo, por lo que el desove nuevos procesos para cada solicitud de OCR funcionó bien en mi situación.

Esta es la función que realiza el 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();
    }
}

I a continuación, se crea una instancia de ImageReader dentro de un bloque usando (que llamar IDisposable.Dispose en salida)

Llamando Marshal.FinalReleaseComObject debe instruir al CLR para liberar los objetos COM, y por lo que estoy en una pérdida para averiguar lo que sería la causa de los síntomas que tenemos.

Por lo que vale, la ejecución de este código fuera de IIS, por ejemplo, en una aplicación de consola, todo parece a prueba de balas. Siempre funciona.

Cualquier consejo que me ayudan a diagnosticar y resolver este problema sería una gran ayuda y voy a upvote como loco! ; -)

Gracias!

¿Fue útil?

Solución

¿Ha pensado en la porción de alojamiento de OCR de la aplicación fuera de proceso .

Tener un servicio que puede dar un montón de flexibilidad:

  1. Se puede definir un punto final simple para su aplicación web, y acceder a ella a través de la interacción remota o WCF.
  2. Si la materia es en forma de pera y la biblioteca es todo lo esquiva, puede hacer que el lanzamiento del servicio un proceso separado cada vez que necesita para realizar OCR. Esto le da la seguridad extrema, sino que implica un pequeño gasto extra. Supongo que OCR es mucho más caro que hace girar un proceso .
  3. Usted puede mantener una instancia alrededor del objeto COM, si la memoria se inicia con fugas puede reiniciar a sí mismo sin impactar en la página web (si se tiene cuidado).

En lo personal he encontrado en el pasado la interoperabilidad COM + IIS = dolor.

Otros consejos

MODI es muy poco firme cuando se trata de deshacerse de la misma, especialmente correr en IIS. En mi experiencia, he encontrado que a pesar de que retrasa todo, la única manera de deshacerse de estos errores es añadir un GC.WaitForPendingFinalizers () después de su GC.Collect () llamada. Si está interesado, escribí un artículo sobre esto.

¿Se puede replicar el problema de una pequeña aplicación de consola? Tal vez dejándolo dormir durante 30 minutos y volver a ella?

La mejor manera de resolver este tipo de cosas es aislar totalmente hacia abajo. Yo estaría interesado en ver cómo funciona.

he tenido que hacer frente a este error hace una semana, y después de probar algunas soluciones que dan aquí, i finalmente se resolvió el problema. Voy a explicar aquí cómo lo hice.

En mi caso tengo un servicio de Windows runing y documentos de procesamiento de una carpeta, el problema se produce cuando hay más de 20 documentos, lanzando el error: Excepción de HRESULT:. 0x80010105 (RPC_E_SERVERFAULT)

En mi código que estaba llamando a un método cada vez que detecto un documento en la carpeta, hago una instancia de documento MODI (MODI.Document _document = new MODI.Document ();) ei procesar el archivo, y que era lo que provoca el error !!

La solución era tener sólo una instancia global de MODI.Document, y procesar todos los documentos de la pizca que, de esta manera tengo sólo una instancia runing para mi servicio de todos los tiempos.

Espero que ayudará a los que se enfrentan el mismo problema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top