2009-08-28 2 views
10

私はMicrosoft Office Document Imaging COM APIの周囲にOCRラッパーライブラリを作成しました。ローカルで実行されるコンソールアプリケーションでは、すべてのテストで完璧に機能します。ASP.Net WebアプリケーションでMODIを使用するにはどうすればよいですか?

悲しいことに、私たちがIIS6でASP.Net Webアプリケーションとして実行しているWCFサービスと統合しようとすると、状況が悪くなり始めます。私たちはMODI COMオブジェクトを解放しようとすることに問題がありました。そして、私たちを助けた多くの例がウェブ上にありました。

しかし、まだ問題が残っています。 IISを再起動してWebアプリケーションを新しくデプロイすると、最初の数回のOCR試行がうまくいきます。 、私はIISをリセットするまで、すべての要求は、OCRを行うには失敗しますこの時点から

The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT)): at MODI.DocumentClass.Create(String FileOpen)

:私は30分ほど放置し、その後、別の要求を行う場合、私はこのようなサーバー障害エラーを取得しますサイクルが再び始まります。

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

更新:この問題は、処理中のOCRの処理を行うことで解決できます。私の状況では、MODIライブラリが管理コードでうまく動かないように見えるので、OCRリクエストごとに新しいプロセスを生成することはうまくいった。私は、Marshal.FinalReleaseComObjectを呼び出す(終了時にIDisposable.Disposeを呼ぶ)を用いてブロック

内部するImageReaderのインスタンスをインスタンス

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

:ここ

はOCRを実行する関数でありますCOMオブジェクトを解放するようにCLRに指示する必要があります。そのため、私たちが持っている症状を引き起こす原因を突き止めることはできません。

IISの外でこのコードを実行する価値があるのは、コンソールアプリケーションでは、すべてが弾丸であるようです。毎回動作します。

私がこの問題を診断して解決するのに役立つヒントは、莫大な助けとなり、私は狂気のようにアップヴォートするでしょう! ;-)

ありがとう!

+0

私に賞金を与えてくれてありがとう、それがあなたを助けてくれてうれしい! –

答えて

4

あなたのアプリのOCR部分をホストすることを考えましたか?アウトプロセスのですか?

サービスを持つことは、あなたの柔軟性のトンを与えることができます:

  1. あなたは、Webアプリケーションのための単純なエンドポイントを定義し、リモートまたはWCF経由でアクセスすることができます。
  2. もし詰め物が梨の形であり、図書館全体がかわすと、あなたはOCRを実行する必要があるたびにサービスを別々のプロセスに立ち上げることができます。これはあなたに極端な安全性を与えますが、わずかな追加費用がかかります。私はOCRは、プロセスをスピンアップするよりもずっと高価だと仮定します。
  3. メモリが漏れ始めると、Webサイトに影響を与えずに自分自身を再起動することができます(注意が必要な場合)。

個人的に私は過去にCOM interop + IIS = griefを見つけました。

+0

こんにちはサム、はい、これは今週ちょうど試したことです。 WCF(およびNetTCPBinding)を使用して、別々にホストされているWindowsサービスにOCRの情報を追加しました。私はIISの下でそれを実行していたときと似たような症状が残っていました。絹のようなヒントに基づいて、(私が書いた短いバージョンのものとは対照的に)長時間実行するコンソールアプリを試し、10分以内に問題を再現することができました。 問題が何であるかにかかわらず、私はあなたの答えを+1します。あなたが概説した理由のために、このようなことをプロセス外で行う方がはるかに意味があるからです。ありがとうございました。 –

+0

ああ、さらに、私は新しいプロセスをスピンアップするとは思っていませんでしたが、これも素晴らしいアイデアです。 COM Interuptの例外をキャッチして、新しいプロセスをスピンアップできるので、実際には、これはちょうどよい回避策かもしれません...クール、私は今興奮しています。私はそれを試して、報告して戻ってきます。再度、感謝します。 –

+0

これは治療になりました。私はWindowsサービスを書いて、WCFサービスをホストして、リクエストごとにOCRの内容をラップする新しいプロセスをスピンアップします。うん、それは高価だと思うが、あなたが指摘したように、それは実際のOCRそのものを行うコストの次に重要ではない。プロセスを閉じるとMODIの相互運用性の問題が正しく解決され、すべてが正常に動作します。 サムと関係するすべての人に感謝します。とても有難い。 –

1

MODIは、特にIISで動作しているときに、それ自体を取り除くことに非常に驚異的です。私の経験では、すべてが減速するものの、これらのエラーを取り除く唯一の方法は、GC.Collect()呼び出しの後にGC.WaitForPendingFinalizers()を追加することです。興味があれば、私はarticleと書きました。

+0

優れた記事、ここでそれを参照してくれてありがとう。 すぐにこの提案を実装し、その結果を助言します。 –

+0

ありがとうございました。うまくいけば、それはあなたの現在の状況であなたを助けてくれるでしょう。 –

+0

悲しいことに、私の問題はまだ残っています。オリジナルの投稿を新しいソースコードで更新し、コミュニティが何を考えるかを見ていきます。とにかく試してくれてありがとう! –

1

小さなコンソールアプリケーションで問題を再現できますか?おそらく30分寝て帰ってくるのだろうか?

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

+0

これは本当に良いアイデアです、ありがとうSilky。私のコンソールテストアプリは決して失敗することはありませんが、私はそれもアイドル状態のままにしていません。テストを実行して終了すると、おそらくCOMオブジェクトへの参照が正しく破棄されます。私は、コンソールアプリケーションを修正し、物事がどのようになっているかをお知らせします。 Cheers –

+0

私の唯一の本当の推測は、何らかの形で互換性のないexeの別のバージョンを実行していることです(たとえば、同じアプリケーションプール内で2つの異なる.netバージョンを実行していて)何とかdllを破壊してしまいます。これは、再起動後に動作する理由を説明します。 –

+0

私はまだこれをまだ解決していませんが、あなたのコメントは信じられないほど役に立ちました。私は長年動いているコンソールアプリケーションで問題を再現することができたので、問題の原因としてIISを取り除くことができます。ヒントのためにもう一度ありがとう。 –

1

私は一週間前にこのエラーに対処しなければなりませんでした。ここにいくつかのソリューションをテストした結果、私は最終的に問題を解決しました。私はここでそれをどのようにして説明します。

私の場合、Windowsサービスを実行してフォルダから文書を処理すると、20を超える文書があり、エラーをスローしたときに問題が発生します。HRESULT:0x80010105(RPC_E_SERVERFAULT)の例外。

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

解決策は、MODI.Documentのグローバルインスタンスを1つしか持たず、すべてのドキュメントを処理していました。

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

関連する問題