7

ファイルを読み取り、データを配列に保存し、いくつかの操作を行うオブジェクトがいくつかあります。オブジェクト A を作成し、オブジェクト A を操作します。 オブジェクト B を作成し、オブジェクト B を操作します。 1 つのオブジェクトが読み取るデータは、10 MB 程度になる場合があります。したがって、最適なオプションは、各オブジェクトを操作した後に各オブジェクトを削除することです。10MB * 1000 オブジェクト = 1GB ではなく、プログラムで約 10 MB のメモリを割り当てたいとします。

オブジェクトは次のようなものです。

class MyClass
{  
    List<string[]> data;

    public MyClass(string datafile)
    {
        using (CsvReader csv = new CsvReader(new StreamReader(datafile), true))
        {
            data = csv.ToList<string[]>();
        }
    }

    public List<string> Operate()
    {
    ...
    }

}

私の質問は: dispose を実装する必要がありますか? そして、次のようなことをしてください:

List<string> results = new List<results>();

using (MyClass m = new MyClass("fileM.txt"))
            {
                results.AddRange(m.Operate());
            }

using (MyClass d = new MyClass("fileD.txt"))
            {
                results.AddRange(d.Operate());
            }

...

管理されていないリソース (ソケット、ストリームなど) を使用する場合は Disposable の実装が推奨されると読みましたが、私のクラスではビッグ データ配列しかありません。

別の方法は、オブジェクトごとに関数を作成することです (GC は、関数で作成されたオブジェクトを自動的に削除すると思います)。

List<string> results = new List<results>();
results.AddRange(myFunction("fileM.txt"));
results.AddRange(myFunction("fileD.txt"));


public List<string> myFunction(string file)
{
MyClass c = new MyClass(file);
return results.AddRange(c.Operate());
}
4

3 に答える 3

5

IDisposableなどは、何も収集されないため、ここでは役に立ちません。このタイプのシナリオでは、おそらく最善のアプローチは、プールを使用して割り当てを減らすことです。つまり、独自のメモリ マネージャーになります。たとえば、あなたList<string>が大きい場合、リストを再利用することで多くの配列を回避できます-明らかにそれらをクリアした後。を呼び出す.Clear()と、バッキング配列はリセットされません。論理マーカーを設定して空と見なすだけです。あなたの特定のケースでは、多くのオブジェクトが個々stringの s になります。それはよりトリッキーですが、少なくともそれらは小さく、ジェネレーション ゼロで収集できるはずです。

于 2013-02-22T02:04:21.267 に答える
3

あなたの場合、単一のバッファ配列を割り当てます。たとえば、10 MB の配列を 1 回割り当てて、必要なデータを入力します。次に、次のオブジェクトに到達したら、配列を再利用します。より大きな配列が必要になった場合は、新しいより大きな配列を割り当てて、代わりにそれを使用できます。ガベージ コレクターは最終的に小さい方を削除します。

a を使用することもできます。List<T>内部的に同じことを行います (配列を割り当て、小さくなりすぎるまで保持し、新しいものを割り当てます)。次のオブジェクトを作成Clearする前に。

ガベージコレクタにオブジェクトの収集を強制することはできないことに注意してください。実際には、ガベージ コレクターが管理されていないリソースをクリーンアップするため、または (ファイル) ハンドルを閉じるためにのみ使用されます。呼び出しは、オブジェクトがメモリから削除されることを保証 (または暗示) しません。IDisposableDispose

ただし、何も変更しない場合でも、コードは正しく、適切に動作します。ガベージ コレクターは、必要なときにいつでも未使用のオブジェクトを削除する責任があり、常に十分なメモリが利用できるようにします。コレクターにその仕事をさせるためにあなたがしなければならない唯一のことは、古いオブジェクトへの参照を手放すことです (それらを上書きするか、それらをnullに設定するか、それらをスコープ外にすることによって)。

1 ) を呼び出して、ガベージ コレクタにデータを収集させることができますGC.Collect()。ただし、これはお勧めできません。ガベージコレクターにそれを自分で理解させてください。

于 2013-02-22T02:05:17.247 に答える
0

.NET 4.0 以降を使用している場合は、BlockingCollectionクラスを確認してください。Int32 パラメーターを受け取るコンストラクターを使用すると、コレクションのサイズの上限を指定できます。AddメソッドとTakeメソッドはスロットルとして機能します。上限に達していない場合にのみ追加が成功します。ある場合は、ブロックされます。Take は、アイテムが存在する場合にのみ成功します。アイテムが存在しない場合は、アイテムが利用可能になるまでブロックされます。もちろん、このクラスにはこれらのメソッドのいくつかのバリエーションがあるため、ドキュメントを十分に調べて、意味のあるものがあるかどうかを確認してください。

于 2013-02-22T02:28:20.960 に答える