Question

J'ai écrit une bibliothèque wrapper OCR autour de l'API Microsoft Office Document Imaging COM, et dans une application console localement en cours d'exécution, il fonctionne parfaitement, avec tous les tests.

Malheureusement, les choses commencent à aller mal quand nous essayons de l'intégrer à un service WCF en cours d'exécution comme une application Web ASP.Net, sous IIS6. Nous avons eu des problèmes autour d'essayer de libérer les objets COM MODI, et il y avait beaucoup d'exemples sur le web qui nous a aidés.

Cependant, des problèmes demeurent. Si je redémarre IIS, et faire un nouveau déploiement de l'application Web, les premières tentatives OCR grand travail. Si je le laisse pendant 30 minutes, puis faire une autre demande, je reçois des erreurs de défaillance du serveur comme ceci:

  

Le serveur a lancé une exception. (Exception de HRESULT: 0x80010105 (RPC_E_SERVERFAULT)): à MODI.DocumentClass.Create (String FichierOuvrir)

A partir de ce moment, toute demande ne parviendra pas à faire l'OCR, jusqu'à ce que je réinitialiser IIS, et le cycle recommence.

Nous courons cette application dans son propre pool d'applications, et il fonctionne sous une identité avec les droits d'administrateur local.

MISE À JOUR: Ce problème peut être résolu en faisant les choses OCR en dehors du processus. Il semble que la bibliothèque ne MODI avec le code managé joue pas bien, en ce qui concerne le nettoyage après lui-même, afin fraie de nouveaux processus pour chaque demande OCR a bien fonctionné dans ma situation.

Voici la fonction qui exécute 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();
    }
}

I instancier puis une instance de ImageReader l'intérieur d'un bloc en utilisant (qui appellera IDisposable.Dispose à la sortie)

L'appel Marshal.FinalReleaseComObject devrait charger le CLR de libérer les objets COM, et donc je suis à une perte de comprendre ce qui cause les symptômes être que nous avons.

Pour ce que ça vaut la peine, l'exécution de ce code en dehors de IIS, dans une application console par exemple, tout semble l'épreuve des balles. Il fonctionne à chaque fois.

Les conseils qui me aider à diagnostiquer et résoudre ce problème serait une immense aide et je vais upvote comme un fou! ; -)

Merci!

Était-ce utile?

La solution

Avez-vous pensé à accueillir la partie OCR de votre application out-of-process .

Avoir un service peut vous donner des tonnes de flexibilité:

  1. Vous pouvez définir d'un simple point final pour votre application Web et y accéder via Remoting ou WCF.
  2. Si des choses est en forme de poire et la bibliothèque est tout d'esquive, vous pouvez avoir le lancement du service d'un processus distinct chaque fois que vous devez effectuer l'OCR. Cela vous donne la sécurité extrême, mais implique une petite dépense supplémentaire. Je suppose que OCR est beaucoup plus cher que tourner un processus .
  3. Vous pouvez garder une instance autour de l'objet COM, si la mémoire commence à vous fuit pouvez-vous redémarrer sans impact sur le site Web (si vous faites attention).

Personnellement, j'ai trouvé dans le passé, le COM Interop + IIS = douleur.

Autres conseils

MODI est incroyablement bancal quand il vient de se débarrasser d'elle-même, en particulier en cours d'exécution dans IIS. Dans mon expérience, je l'ai trouvé que même si elle ralentit tout, la seule façon de se débarrasser de ces erreurs est d'ajouter un GC.WaitForPendingFinalizers () après l'appel GC.Collect (). Si vous êtes intéressé, j'ai écrit un article à ce sujet.

Pouvez-vous reproduire le problème dans une petite application de la console? laissant peut-être dormir pendant 30 minutes et y revenir?

La meilleure façon de résoudre les choses comme celle-ci est de l'isoler totalement vers le bas. Je serais curieux de voir comment cela fonctionne.

Je devais traiter cette erreur il y a une semaine, et après avoir testé quelques solutions qui donnent ici, je me suis finalement résolu le problème. Je vais ici vous expliquer comment je l'ai fait.

Dans mon cas, j'ai un service Windows runing et les documents de traitement d'un dossier, le problème se produit quand il y a plus de 20 documents, jetant l'erreur: Exception de HRESULT:. 0x80010105 (RPC_E_SERVERFAULT)

Dans mon code, j'ai appelé une méthode chaque fois que je perçois un document dans le dossier, je fais une instance du document MODI (MODI.Document _document = new MODI.Document ();) et i traiter le fichier, et que était ce qui cause l'erreur !!

La solution était d'avoir une seule instance globale de MODI.Document, et traiter tous les documents whit il, de cette façon j'ai une seule instance runing pour mon service tout le temps.

J'espère que cela aidera ceux qui sont confrontés au même problème.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top