10

Microsoft Office Document Imaging COM API の OCR ラッパー ライブラリを作成しました。ローカルで実行されているコンソール アプリでは、すべてのテストで問題なく動作します。

悲しいことに、IIS6 の下で ASP.Net Web アプリケーションとして実行されている WCF サービスと統合しようとすると、うまくいきません。MODI COM オブジェクトを解放しようとする際に問題がありましたが、ウェブ上に参考になる例がたくさんありました。

しかし、問題はまだ残っています。IIS を再起動し、Web アプリを新たに展開すると、最初の数回の OCR 試行はうまく機能します。30 分ほど放置してから別のリクエストを行うと、次のようなサーバー障害エラーが発生します。

サーバーが例外をスローしました。(HRESULT からの例外: 0x80010105 (RPC_E_SERVERFAULT)): MODI.DocumentClass.Create (String FileOpen) で

この時点から、IIS をリセットするまで、すべての要求は OCR を実行できず、サイクルが再び開始されます。

このアプリケーションは独自のアプリケーション プールで実行され、ローカル管理者権限を持つ ID の下で実行されます。

更新: この問題は、OCR をアウト プロセスで実行することで解決できます。MODI ライブラリはマネージ コードとうまく連携していないように見えるので、OCR リクエストごとに新しいプロセスを生成すると、私の状況ではうまくいきました。

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();
    }
}

次に、using ブロック内で ImageReader のインスタンスをインスタンス化します (終了時に IDisposable.Dispose を呼び出します)。

Marshal.FinalReleaseComObject を呼び出すと、CLR に COM オブジェクトを解放するように指示されます。そのため、発生している症状の原因を突き止めることができません。

価値があるのは、このコードを IIS の外部で、たとえばコンソール アプリで実行すると、すべてが防弾のように見えることです。毎回動作します。

この問題を診断して解決するのに役立つヒントは、非常に役立ちます。私は狂ったように賛成します! ;-)

ありがとう!

4

4 に答える 4

4

アプリの OCR 部分をプロセス外でホストすることを考えたことはありますか。

サービスを利用すると、非常に多くの柔軟性が得られます。

  1. Web アプリケーションの単純なエンドポイントを定義し、リモート処理または WCF を介してアクセスできます。
  2. 物が洋ナシの形をしていて、ライブラリがすべて回避されている場合、OCR を実行する必要があるたびに、サービスに別のプロセスを起動させることができます。これにより、非常に安全になりますが、わずかな追加費用がかかります。OCR は、プロセスをスピンアップするよりもはるかにコストがかかると思います。
  3. COM オブジェクトの周りにインスタンスを保持できます。メモリ リークが発生した場合は、Web サイトに影響を与えずに再起動できます (注意が必要です)。

個人的には、過去に COM 相互運用 + IIS = 悲しみを発見しました。

于 2009-09-09T03:25:18.317 に答える
1

私は一週間前にこのエラーに対処しなければなりませんでした。ここでは、私がどのようにそれを行ったかを説明します。

私の場合、フォルダーからドキュメントを実行して処理するWindowsサービスがあります.20を超えるドキュメントがあると問題が発生し、エラーがスローされます: HRESULTからの例外: 0x80010105 (RPC_E_SERVERFAULT).

私のコードでは、フォルダー内のドキュメントを検出するたびにメソッドを呼び出していました。MODI ドキュメントのインスタンスを作成し (MODI.Document _document = new MODI.Document();)、ファイルを処理しました。それが原因でした。エラー!!

解決策は、MODI.Document のグローバル インスタンスを 1 つだけ持ち、すべてのドキュメントを処理することでした。このようにして、サービスに対して常に 1 つのインスタンスのみを実行します。

同じ問題に直面している人々に役立つことを願っています。

于 2010-11-26T13:37:13.503 に答える
1

小さなコンソール アプリケーションで問題を再現できますか? おそらく、30分間スリープさせてから戻ってきますか?

このような問題を解決する最善の方法は、完全に隔離することです。それがどのように機能するか興味があります。

于 2009-09-09T01:27:09.040 に答える
1

MODI は、特に IIS で実行されている場合、それ自体を取り除くことに関しては信じられないほど不安定です。私の経験では、すべてが遅くなりますが、これらのエラーを取り除く唯一の方法は、GC.Collect() 呼び出しの後に GC.WaitForPendingFinalizers() を追加することです。興味があれば、私はこれについて記事を書きました。

于 2009-08-28T14:06:13.830 に答える