18

私が書いている小さな趣味のゲームのために、簡単なリソースマネージャーを書こうとしています。このリソースマネージャーが実行する必要のあるタスクの1つは、未使用のリソースをアンロードすることです。私はこれを2つの方法で行うことを考えることができます:

  • オブジェクトがリソースへの参照を必要としなくなったら、リソースマネージャーのメソッドを呼び出して、オブジェクトが使用されなくなったことを示す必要があります。また

  • オブジェクトがリソースへの参照を必要としなくなった場合、オブジェクトは単にnullに設定されます。次に、リソースマネージャーが未使用のリソースをアンロードするように求められると、各リソースの参照カウントを(リフレクションを介して?)取得します。参照カウントが1の場合(リソースマネージャーはリソースへの参照を持ちます)、リソースをアンロードします。

C#で2番目のソリューションを実現する方法はありますか?ありがとう。

4

5 に答える 5

35

カップルのもの。まず、オブジェクトは参照カウントされません。参照カウント方式には循環参照の問題があり、2つのオブジェクトは相互に参照しますが、それ以外の場合はアクセスできず、リークが発生します。.NETは、参照カウントを使用しないマークアンドスイープアプローチを使用します。

第二に、弱参照を使用するという提案はひどいものではありませんが、スラムダンクでもありません。パフォーマンス上の理由からキャッシュを構築しています。(アプリケーションのパフォーマンス特性に関する注意深く、経験的で現実的な調査により、許容可能なパフォーマンスを達成するためにキャッシュ戦略が必要であることが説得力を持って実証されたと思います。そうでない場合は、これらの決定を時期尚早に行っています。)キャッシュは、リソースを解放するタイミングについてポリシーを設定する必要があります。そうしないと、メモリリークが発生します。

GCポリシーとポリシーが同等のポリシーであることをどのように知っていますか?GCは、特定のパフォーマンスニーズを念頭に置いて設計されていません。つまり、これは実際にはゴミであるリソースを解放するように設計されており、念頭に置いている特定のパフォーマンス目標を達成するためではありません。決定をGCに委任することにより、パフォーマンスのニーズに合わせてキャッシュポリシーを調整する機能を放棄します。

于 2009-11-06T15:25:08.633 に答える
15

WeakReferenceリソースマネージャーから使用できるように思えます。残りはGCが行います。少しキャストする必要がありますが、それは簡単で、機能します。

class Manager {
    Dictionary<string, WeakReference> refs =
        new Dictionary<string, WeakReference>();
    public object this[string key] {
        get {
            WeakReference wr;
            if (refs.TryGetValue(key, out wr)) {
                if(wr.IsAlive) return wr.Target;
                refs.Remove(key);
            }
            return null;
        }
        set {
            refs[key] = new WeakReference(value);
        }
    }
}
static void Main() {
    Manager mgr = new Manager();
    var obj = new byte[1024];
    mgr["abc"] = obj;

    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    Console.WriteLine(mgr["abc"] != null); // true (still ref'd by "obj")

    obj = null;
    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
    Console.WriteLine(mgr["abc"] != null); // false (no remaining refs)
}
于 2009-11-06T09:25:09.020 に答える
2

.NETには、ガベージコレクタと呼ばれるリソースマネージャがすでにあります。したがって、非常に効率的なアプローチは、参照をnullに設定し、何もしないことです。

より直接的な答え:いいえ、オブジェクトの参照を取得する方法はありません。

WeakReferenceクラスを学習するか、Cachingシステムを使用することをお勧めします。

于 2009-11-06T09:23:46.883 に答える
1

リソースマネージャーがリソースWeakReferenceにsを使用していることを確認します。そうすれば、他の誰もリソースを参照していないときに、ガベージコレクションの対象になります。

于 2009-11-06T09:24:50.097 に答える
0

他のユーザーがすでに言っているように、達成しようとしていることはすでにGCによって作成されており、WeakReferenceを使用して微調整できます。

これは、.NET、Javaなどの管理対象環境では、これは問題ではないことを意味します。

低レベルのフレームワークアーキテクチャはメモリ管理からあなたを隔離するので、それでもその種の機能が必要な場合は、独自のコードアーキテクチャを確認することを強くお勧めします。メモリ管理

于 2009-11-06T10:06:22.083 に答える