Domanda

Ho scritto una libreria wrapper OCR intorno alla API di Microsoft Office Document Imaging COM, e in una console app in esecuzione a livello locale, funziona perfettamente, con ogni test.

Purtroppo, le cose iniziano ad andare male quando tentiamo di integrarlo con un servizio WCF in esecuzione come un'applicazione Web ASP.Net, sotto IIS6. Abbiamo avuto problemi in giro cercando di liberare gli oggetti MODI COM, e c'erano un sacco di esempi sul web che ci ha aiutato.

Tuttavia, rimangono ancora problemi. Se ho riavviato IIS, e fare una distribuzione fresca della web app, i primi tentativi di OCR grande lavoro. Se lascio per 30 minuti o giù di lì, e poi fare un'altra richiesta, ricevo errori guasto del server come questo:

  

Il server ha generato un'eccezione. (Eccezione da HRESULT: 0x80010105 (RPC_E_SERVERFAULT)): a MODI.DocumentClass.Create (String FileOpen)

Da questo momento in poi, ogni richiesta non riuscirà a fare l'OCR, fino a quando ho reimpostare IIS, e il ciclo ricomincia.

Noi usiamo questa applicazione in un suo App Pool, e gira sotto un'identità con diritti di amministratore locale.

UPDATE: Questo problema può essere risolto facendo la roba OCR dal processo. Sembra come se la libreria MODI non gioca bene con codice gestito, quando si tratta di pulizia dopo se stessa, così generando nuovi processi per ogni richiesta OCR funzionava bene nella mia situazione.

Questa è la funzione che esegue l'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();
    }
}

Poi istanziare ImageReader all'interno di un blocco utilizzando (che chiamerà IDisposable.Dispose all'uscita)

Calling Marshal.FinalReleaseComObject dovrebbe incaricare il CLR per rilasciare gli oggetti COM, e quindi sono in perdita per capire quello che sarebbe la causa dei sintomi che abbiamo.

Per quel che vale, l'esecuzione di questo codice esterno di IIS, nel dire una console app, tutto sembra a prova di proiettile. Funziona ogni volta.

Qualche consiglio che mi aiutano a diagnosticare e risolvere questo problema sarebbe di grande aiuto e io upvote come un matto! ; -)

Grazie!

È stato utile?

Soluzione

Avete pensato di ospitare la parte della vostra applicazione OCR out-of-process .

Avere un servizio può dare tonnellate di flessibilità:

  1. È possibile definire un semplice punto finale per l'applicazione Web e accedervi tramite i servizi remoti o WCF.
  2. Se è roba forma di pera e la biblioteca è tutto Dodge, si può avere il lancio del servizio di un processo separato ogni volta che è necessario eseguire l'OCR. Questo ti dà estrema sicurezza, ma comporta una piccola spesa extra. Parto dal presupposto che OCR è molto più costoso di filatura di un processo .
  3. È possibile mantenere un'istanza intorno dell'oggetto COM, se la memoria inizia a perdere è possibile riavviare da soli senza impattare il sito web (se si sta attenti).

Personalmente ho trovato in passato l'interoperabilità COM + IIS = dolore.

Altri suggerimenti

MODI è incredibilmente wonky quando si tratta di sbarazzarsi di sé, soprattutto in esecuzione in IIS. Nella mia esperienza, ho trovato che, anche se rallenta tutto giù, l'unico modo per sbarazzarsi di questi errori è di aggiungere un GC.WaitForPendingFinalizers () dopo il vostro GC.Collect) chiamata (. Se siete interessati, ho scritto un articolo su questo.

Si può replicare il problema in una piccola applicazione console? Forse lasciando dormire per 30 minuti e tornare ad esso?

Il modo migliore per risolvere le cose come questo è quello di isolare completamente il basso. Sarei curioso di vedere come funziona.

Ho avuto a che fare con questo errore una settimana fa, e dopo aver provato alcune soluzioni che danno qui, ho finalmente risolto il problema. Mi spiego qui come ho fatto.

Nel mio caso ho un servizio di Windows di matricola e l'elaborazione di documenti da una cartella, il problema si verifica quando ci sono più di 20 documenti, gettando l'errore: Eccezione da HRESULT:. 0x80010105 (RPC_E_SERVERFAULT)

Nel mio codice mi stava chiamando un metodo ogni volta che rilevo un documento nella cartella, faccio un esempio di documento MODI (MODI.Document _document = new MODI.Document ();) e ho elaborare il file, e che era quello che causa l'errore !!

La soluzione era di avere una sola istanza globale di MODI.Document, e il processo di tutti i documenti briciolo di esso, in questo modo non ho una sola istanza di matricola per il mio servizio di tutti i tempi.

Spero che aiuterà coloro che si trovano ad affrontare lo stesso problema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top