2017-11-07 10 views
0

私は最近サービスに変換したC#アプリケーションを持っています。通常の操作の一環として、次のコードを使用してCRを経由してPDFの請求書を作成します。Crystal Reportsはガベージコレクションにもかかわらずジョブの制限に達します

foreach (string docentry in proformaDocs) 
    using (ReportDocument prodoc = new ReportDocument()) { 
     string filename = outputFolder + docentry + ".pdf"; 
     prodoc.Load(/* .rpt file */); 
     prodoc.SetParameterValue(0, docentry); 
     prodoc.SetParameterValue(1, 17); 
     prodoc.SetDatabaseLogon(/* login data */); 
     prodoc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, 
           filename); 
     prodoc.Close(); 
     prodoc.Dispose(); 
    } 

foreach (string docentry in invoiceDocs) 
    using (ReportDocument invdoc = new ReportDocument()) { 
     string filename = differentOutputFolder + docentry + ".pdf"; 
     invdoc.Load(/* different .rpt file */); 
     invdoc.SetParameterValue(0, docentry); 
     invdoc.SetParameterValue(1, 13); 
     invdoc.SetDatabaseLogon(/* login data */); 
     invdoc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, 
           filename); 
     invdoc.Close(); 
     invdoc.Dispose(); 
    } 

GC.Collect(); 

問題は、ほとんどの2分ごとに実行される上記のコードで実行時の約3~4時間、負荷(後に、あります)操作では、明示的にレポートオブジェクトを廃棄しても、処理ジョブの制限に達します。しかし、サービスを実行したままにして、同じアプリケーションの非サービスインスタンスを起動すると、サービスがまだジョブ制限例外をスローしている間も、そのアプリケーションは正常に実行されます。非サービスインスタンスが処理を担当しているので、サービスは現時点では何もしませんが、サービスが手動で停止してサービスを再開するまでエラーを再送信します。その時点でエラーは消え去りますさらに3〜4時間。

すべての単一のレポートオブジェクトを処理したらすぐに処理し、処理と廃棄の各ラウンド後にガベージコレクションを呼び出すと、どのようにジョブの制限にぶつかるのですか?ジョブの制限に達すると、同じコードのパラレルインスタンスはどのように影響を受けませんか?


更新:私は問題を追跡することができましたが、それはCRではないことがわかりました。これは、スレッドをフリーズ呼び出し、何らかの理由で

public Company GetSAP(string name) { 
    Database db;     //wrapper class 
    SAP.TryGetValue(name, out db); //fetching from the Dictionary 
    return db.SAP;     //Company object in the wrapper class 
} 

が、タイマーは、サービスの正常な動作を開始:私はこれで、辞書に保存されているデータベースのラッパークラス内でフェッチされたSAP社のオブジェクトからCRのデータベース・ログイン資格証明を取ります自然にそれが完了するのを待たずに、別のスレッドを起動します。これは、これを呼び出すとフリーズします。これは、固定されたスレッドの数がジョブの制限に達するまで維持されます。その時点で、まだ制限されたスレッドがジョブの制限を満たすため、新しいスレッドごとに例外がスローされます。あるスレッドがまだ実行中で、上記の関数を呼び出すとアプリケーションが凍結した場合、新しいスレッドを起動しないようにチェックを入れました。

上記のreturn db.SAPオブジェクトのゲッターは、return以外の文字は何も含まれていません。

+0

'GC.Collect'を明示的に呼び出さないでください。それはコードのにおいであり、99で必要とされません。(9)%の場合。また 'ReportDocument'オブジェクトに対して' close'と 'Dispose'を呼び出す必要はありません。これは' using'ステートメントのために自動的に行われるからです。 – dymanoid

+0

多くのレポート文書を読み込んだらLOHフラグメンテーションのように思えます。 「ヒット処理の仕事の制限」とはどういう意味ですか?どんな種類の例外がありますか?私はよくCRを知らない。 –

+0

@ KonradKokosa 「レポートの読み込みに失敗しました」というメッセージが表示され、InteropServices.COMExceptionの内部例外として「システム管理者によって設定された最大レポート処理ジョブ制限に達しました」というメッセージが表示されます。デフォルトでは75個の同時ジョブのグローバルな制限がありますが、一度に多数のジョブを処理することはなく、上記のように制限に達するずっと前にガベージコレクションを行う必要があります。それでなぜ私はこのことに困惑しているのですか? – amitakartok

答えて

0

申し訳ありませんが、問題はちょっと解決されました。何らかの理由で、COMオブジェクト内のゲッターは、サービスからアクセスされた場合にフリーズからログイン資格をフェッチしようとしましたが、サービス以外のアプリケーションからは取得できませんでした。このCOMオブジェクトをラッパークラスに埋め込んで、IISアプリケーションの辞書設定をテストすると、フリーズは発生しませんでした。私は、COMオブジェクトのソースコードをSAPが共有している理由とその理由が分かりません。私はこれまで考え出したことはありません。だから私は、資格情報を格納するための文字列フィールドをいくつか宣言し、COMオブジェクトを必要としないので、COMオブジェクトへのアクセスを完全に中止しました。

関連する問題