He escrito una biblioteca de contenedor de OCR alrededor de la API COM de Microsoft Office Document Imaging, y en una aplicación de consola que se ejecuta localmente, funciona perfectamente, con cada prueba.¿Cómo uso MODI en una aplicación web ASP.Net?
Lamentablemente, las cosas empiezan a ir mal cuando intentamos integrarlo con un servicio WCF que se ejecuta como una aplicación web ASP.Net, bajo IIS6. Tuvimos problemas para liberar los objetos COM de MODI y hubo muchos ejemplos en la web que nos ayudaron.
Sin embargo, aún persisten los problemas. Si reinicio IIS y realizo una nueva implementación de la aplicación web, los primeros pocos intentos de OCR funcionan bien. Si lo dejo durante 30 minutos más o menos, y luego hacer otra solicitud, recibo errores falla en el servidor como este:
The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT)): at 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.
Ejecutamos esta aplicación en su propio grupo de aplicaciones y se ejecuta con una identidad con derechos de administrador local.
ACTUALIZACIÓN: Este problema se puede resolver haciendo que el material de OCR esté fuera de proceso. Parece que la biblioteca MODI no funciona bien con el código administrado, cuando se trata de limpiar por sí mismo, por lo que generar nuevos procesos para cada solicitud de OCR funcionó bien en mi situación.
Aquí 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();
}
}
entonces se crea una instancia de ImageReader dentro de un bloque usando (que se llame a la salida IDisposable.Dispose)
Calling Marshal.FinalReleaseComObject debería instruir al CLR para que libere los objetos COM, por lo que no sé qué causaría los síntomas que tenemos.
Por lo que vale la pena, ejecutar este código fuera de IIS, por ejemplo, una aplicación de consola, todo parece a prueba de balas. Funciona todo el tiempo.
¡Cualquier consejo que me ayude a diagnosticar y resolver este problema sería una gran ayuda y me volvería loco! ;-)
Gracias!
Gracias por concederme la recompensa, ¡me alegro de que te haya ayudado! –