0

データセットを生成し、そこから xml ファイルを作成する関数があります。機能は完璧に機能しています。問題は、レポートを数回実行した後に「メモリ不足」エラーが発生することです。レポートをテストしたところ、この XmlDocument コマンドに到達するとメモリ使用量が大幅に増加することがわかりました。GC を使用しましたが、使用しませんでした。何か提案はありますか?

if (ddlDir.SelectedItem != null && ddlSec.SelectedItem != null)
{
    using (DataSet dsClosedKPICalls = GetReportData())
    {
        dsClosedKPICalls.DataSetName = "ClosedKPICalls";
        foreach (DataTable table in dsClosedKPICalls.Tables)
        {
            table.TableName = "ServiceInfo";
        }
        XmlContent = dsClosedKPICalls.GetXml();
    }

    XmlDocument XML_Data = new XmlDocument();           // contains the resultant XML data

    XML_Data.LoadXml(XmlContent);
    XmlNodeList TablesList = XML_Data.SelectNodes("ClosedKPICalls/ServiceInfo");

    for (int i = 0; i < TablesList.Count; i++)
    {
        XmlDocument innerXML = new XmlDocument();

        using (DataSet dsTaskDetails = getSplitupRecords(TablesList.Item(i).SelectSingleNode("ServiceNo").InnerText))
        {
            dsTaskDetails.DataSetName = "TaskDetails";
            foreach (DataTable tbl in dsTaskDetails.Tables)
            {
                tbl.TableName = "RequestInfo";
            }

            innerXML.LoadXml(dsTaskDetails.GetXml());

            TablesList.Item(i).AppendChild(XML_Data.ImportNode(innerXML.SelectSingleNode("TaskDetails"), true));

            innerXML = null;
            GC.Collect();
            GC.WaitForPendingFinalizers();
        }
    }
}
4

1 に答える 1

2

XML ドキュメントのサイズは? 具体的には、約 85K より大きいですか?

.Net フレームワークは、最大 85K を超える割り当てに使用されるラージ オブジェクト ヒープ (LOH)と呼ばれるものを使用します。XML ドキュメントがこれよりも大きい場合、 (文字列などの)ものはおそらく LOH に割り当てられます。LOH の問題は、圧縮されていないため、メモリの断片化の影響を受けやすくOutOfMemoryExceptions、プロセスが通常そのメモリを割り当てることができる場合でもスローされる可能性があることです。これ問題の原因である可能性があります。

解決策については、次のいずれかを試すことができます

  • オブジェクトのサイズを 85K 未満に保つようにして、LOH の使用を減らします。アプリケーションによっては、これを実現するのが難しい場合がありますが、(たとえば) 大きな XML ドキュメントを多数の小さなドキュメントに分割できる場合があります。
  • .Net フレームワーク v4.5 をターゲットにして、それが役立つかどうかを確認してください。.Net フレームワーク v4.5 には、この場合に役立つ可能性のある LOH の改善が含まれています。

余談ですが、GC.Collectandへの呼び出しGC.WaitForPendingFinalizersは悪い考えです。これは、低世代のオブジェクトを高世代に人為的に昇格させ、一般に「ガベージコレクターを台無しにする」可能性があるためです。この場合、これらの呼び出しもほぼ確実に役に立ちません。原則として、自分が何をしているのかを正確に理解していない限り、ガベージ コレクションを手動で呼び出すことは避けるべきです。

于 2012-09-25T13:46:09.433 に答える