Как мне использовать MODI в ASP.Net Веб-приложении?

StackOverflow https://stackoverflow.com/questions/1344510

  •  20-09-2019
  •  | 
  •  

Вопрос

Я написал библиотеку-оболочку для распознавания текста вокруг COM API Microsoft Office Document Imaging, и в локально запущенном консольном приложении она работает безупречно при каждом тестировании.

К сожалению, дела начинают идти плохо, когда мы пытаемся интегрировать его со службой WCF, работающей как ASP.Net Веб-приложение под управлением IIS6.У нас возникли проблемы при попытке освободить COM-объекты MODI, и в Интернете было множество примеров, которые нам помогли.

Однако проблемы все еще остаются.Если я перезапущу IIS и выполню новое развертывание веб-приложения, первые несколько попыток распознавания будут выполнены отлично.Если я оставляю это на 30 минут или около того, а затем выполняю другой запрос, я получаю ошибки сбоя сервера, подобные этой:

Сервер выдал исключение.(Исключение из HRESULT:0x80010105 (ОШИБКА RPC_E_SERVERFAULT)):в MODI.DocumentClass.Создать (открыть строковый файл)

С этого момента каждый запрос не сможет выполнить распознавание, пока я не сброшу IIS и цикл не начнется снова.

Мы запускаем это приложение в его собственном пуле приложений, и оно работает под идентификатором с правами локального администратора.

Обновить:Эту проблему можно решить, выполнив распознавание текста вне процесса.Похоже, что библиотека MODI плохо работает с управляемым кодом, когда дело доходит до очистки за собой, поэтому создание новых процессов для каждого запроса 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();
    }
}

Затем я создаю экземпляр ImageReader внутри блока using (который будет вызывать IDisposable.Утилизировать при выходе)

Вызываю Marshal.FinalReleaseComObject должен дать указание CLR освободить COM-объекты, и поэтому я затрудняюсь выяснить, что могло бы вызвать имеющиеся у нас симптомы.

Как бы то ни было, при запуске этого кода вне IIS, скажем, в консольном приложении, все кажется пуленепробиваемым.Это срабатывает каждый раз.

Любые советы, которые помогут мне диагностировать и решить эту проблему, окажут огромную помощь, и я буду голосовать как сумасшедший!;-)

Спасибо!

Это было полезно?

Решение

Думали ли вы о размещении OCR-части вашего приложения вышедший из процесса.

Наличие сервиса может предоставить вам массу гибкости:

  1. Вы можете определить простую конечную точку для своего веб-приложения и получить к ней доступ через удаленное подключение или WCF.
  2. Если материал имеет грушевидную форму, а вся библиотека - dodge, вы можете попросить службу запускать отдельный процесс каждый раз, когда вам нужно выполнить распознавание текста.Это обеспечивает вам исключительную безопасность, но сопряжено с небольшими дополнительными расходами.Я бы предположил , что Распознавание текста НАМНОГО дороже, чем запуск процесса.
  3. Вы можете сохранить экземпляр COM-объекта, если начнется утечка памяти, вы можете перезапустить себя, не оказывая влияния на веб-сайт (если вы будете осторожны).

Лично я обнаружил в прошлом COM-взаимодействие + IIS = горе.

Другие советы

MODI невероятно неудобен, когда дело доходит до избавления от самого себя, особенно при работе в IIS.По своему опыту я обнаружил, что, хотя это все замедляет, единственный способ избавиться от этих ошибок - добавить GC.WaitForPendingFinalizers() после вашего GC.Вызов Collect().Если вам интересно, я написал Статья об этом.

Можете ли вы воспроизвести проблему в небольшом консольном приложении?Может быть, оставить его спать на 30 минут и вернуться к нему?

Лучший способ решить подобные проблемы - полностью изолировать их.Мне было бы интересно посмотреть, как это работает.

Мне пришлось столкнуться с этой ошибкой неделю назад, и после тестирования некоторых решений, приведенных здесь, я, наконец, решил проблему.Я объясню здесь, как я это сделал.

В моем случае у меня есть служба Windows, запускающая и обрабатывающая документы из папки, проблема возникает, когда имеется более 20 документов, выдающих ошибку:Исключение из HRESULT:0x80010105 (ОШИБКА RPC_E_SERVERFAULT).

В моем коде я вызывал метод каждый раз, когда я обнаруживал документ в папке, я создавал экземпляр MODI document (MODI.Document _document = new MODI.Document();) и обрабатывал файл, и это было причиной ошибки!!

Решение состояло в том, чтобы иметь только один глобальный экземпляр MODI.Document и обрабатывать все документы с его помощью, таким образом, у меня всегда работает только один экземпляр для моего сервиса.

Я надеюсь, что это поможет тем, кто сталкивается с той же проблемой.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top