Pergunta

Eu escrevi uma biblioteca de wrapper OCR em torno da API da Microsoft Office Document Imaging API e, em um aplicativo de console em execução localmente, ele funciona perfeitamente, a cada teste.

Infelizmente, as coisas começam a ficar mal quando tentamos integrá -lo a um serviço WCF em execução como um aplicativo Web ASP.NET, no IIS6. Tivemos problemas em tentar liberar os objetos Modi com, e havia muitos exemplos na web que nos ajudaram.

No entanto, os problemas ainda permanecem. Se eu reiniciar o IIS e fazer uma nova implantação do aplicativo da web, as primeiras tentativas de OCR funcionam muito bem. Se eu deixar por 30 minutos ou mais e depois fizer outra solicitação, recebo erros de falha do servidor como este:

O servidor lançou uma exceção. (Exceção de HRESULT: 0x80010105 (rpc_e_serverfault)): em modi.documentclass.create (string fileopen)

A partir deste ponto, cada solicitação não fará o OCR, até eu redefinir o IIS, e o ciclo começar novamente.

Executamos esse aplicativo em seu próprio pool de aplicativos e ele é executado sob uma identidade com os direitos de administrador local.

ATUALIZAÇÃO: Este problema pode ser resolvido fazendo o material do OCR fora do processo. Parece que a biblioteca Modi não joga bem com o código gerenciado, quando se trata de limpar depois de si, portanto, a geração de novos processos para cada solicitação de OCR funcionou bem na minha situação.

Aqui está a função que executa o 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();
    }
}

Em seguida, instanciei uma instância de ImageReader dentro de um bloco de uso (que chamará idisposable.Dispose on Sair)

Chamar marshal.FinalReleasEComObject deve instruir o CLR a liberar os objetos COM, e, portanto, não estou sem descobrir o que estaria causando os sintomas que temos.

Pelo que vale a pena, executando esse código fora do IIS, em um aplicativo de console, tudo parece à prova de balas. Funciona sempre.

Quaisquer dicas que me ajudem a diagnosticar e resolver esse problema seriam uma imensa ajuda e eu votarei como louco! ;-)

Obrigado!

Foi útil?

Solução

Você já pensou em hospedar a parte OCR do seu aplicativo fora do processo.

Ter um serviço pode lhe dar toneladas de flexibilidade:

  1. Você pode definir um ponto final simples para o seu aplicativo da Web e acessá -lo por meio de remoção ou WCF.
  2. Se o material é a forma de pêra e a biblioteca é toda a Dodge, você pode lançar o serviço um processo separado toda vez que precisar executar o OCR. Isso oferece segurança extrema, mas envolve uma pequena despesa extra. Eu assumiria isso OCR é muito mais caro do que aumentar um processo.
  3. Você pode manter uma instância em torno do objeto COM, se a memória começar a vazar, você poderá se reiniciar sem afetar o site (se tiver cuidado).

Pessoalmente, encontrei no passado o COM INTEROP + IIS = sofrimento.

Outras dicas

Modi é incrivelmente instável quando se trata de se livrar de si mesmo, especialmente correndo no IIS. Na minha experiência, descobri que, embora isso diminua tudo, a única maneira de se livrar desses erros é adicionar um GC.WaitPorpendingFinalizers () após sua chamada gc.collect (). Se você estiver interessado, escrevi um artigo sobre isso.

Você pode replicar o problema em um pequeno aplicativo de console? Talvez deixando -o dormir por 30 minutos e voltar a ele?

A melhor maneira de resolver coisas como essa é isolá -lo totalmente. Eu estaria interessado em ver como isso funciona.

Eu tive que lidar com esse erro há uma semana e, depois de testar algumas soluções dando aqui, finalmente resolvi o problema. Vou explicar aqui como fiz isso.

No meu caso, tenho um Windows Service Runing and Processing Documents de uma pasta, o problema ocorre quando há mais de 20 documentos, lançando o erro: Exceção do HRESULT: 0x80010105 (RPC_E_SERVERFAULT).

No meu código, eu chamava um método cada vez que detecto um documento na pasta, faço uma instância do documento Modi (Modi.document _document = new Modi.document ();) e processei o arquivo, e foi isso que causa o que causa o erro!!

A solução era ter apenas uma instância global do Modi.Document e processar todos os documentos, dessa maneira, tenho apenas uma execução de instância para o meu serviço o tempo todo.

Espero que isso ajude aqueles que estão enfrentando o mesmo problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top