0

マップの個々の領域が動的に生成されるか、既に生成されて保存されている場合はファイルからロードされるプロジェクトに取り組んでいます。リージョンは必要に応じてロード/生成され、不要になったときに保存および破棄されます。このマップの 1 つ以上の領域をさまざまな目的で使用するいくつかの異なるタスクがあります。たとえば、これらのタスクの 1 つは、現在表示されているすべての領域 (常に約 9 つ) を描画することです。もう 1 つは、リージョンに関する情報を取得したり、リージョンを変更したりすることです。問題は、これらのタスクが他のタスクと同じリージョンで機能する場合と機能しない場合があることです。

これらの領域はかなり大きく、生成にコストがかかるため、タスクごとに異なるコピーを使用するのは (これらの理由やその他の理由で) 問題があります。むしろ、現在ロードされているリージョンのプールを作成して管理するのが良い考えだと思います。新しいタスクは、最初に必要なリージョンのプールをチェックします。存在する場合はそれを使用するか、新しいものを作成してプールに追加します。

それが機能する場合、このプールをどのように管理しますか? 領域がどのタスクにも不要になり、安全に破棄できるかどうかを判断するにはどうすればよいですか? 私はばかげていて、これを過度に複雑にしていますか?

それが誰にとっても重要な場合、私はc#を使用しています。

編集:私はもっと目覚めたので、使用されている場所ごとに各地域のカウンターをインクリメントするのと同じくらい簡単でしょうか? カウンターが0になったら捨てる?

4

2 に答える 2

1

それが機能する場合、このプールをどのように管理しますか? 領域がどのタスクにも不要になり、安全に破棄できるかどうかを判断するにはどうすればよいですか?

これを行う簡単な方法は、弱参照を使用することです。

public class RegionStore
{
  // I'm using int as the identifier for a region.
  // Obviously this must be some type that can serve as
  // an ID according to your application's logic.
  private Dictionary<int, WeakReference<Region>> _store = new Dictionary<int, WeakReference<Region>>();
  private const int TrimThreshold = 1000; // Profile to find good value here.
  private int _addCount = 0;
  public bool TryGetRegion(int id, out Region region)
  {
    WeakReference<Region> wr;
    if(!_store.TryGetValue(id, out wr))
      return false;
    if(wr.TryGetTarget(out region))
      return true;
    // Clean up space in dictionary.
    _store.Remove(id);
    return false;
  }
  public void AddRegion(int id, Region region)
  {
    if(++_addCount >= TrimThreshold)
      Trim();
    _store[id] = new WeakReference<Region>(region);
  }
  public void Remove(int id)
  {
    _store.Remove(id);
  }
  private void Trim()
  {
    // Remove dead keys.
    // Profile to test if this is really necessary.
    // If you were fully implementing this, rather than delegating to Dictionary,
    // you'd likely see if this helped prior to an internal resize.
    _addCount = 0;
    var keys = _store.Keys.ToList();
    Region region;
    foreach(int key in keys)
      if(!_store[key].TryGetTarget(out wr))
        _store.Remove(key);
  }
}

これでオブジェクトのストアが作成されましたが、Regionオブジェクトへの他の参照が存在しない場合、そのストアはオブジェクトのガベージ コレクションを妨げません。

特定のタスクは領域を変更します。この場合、領域オブジェクトで「更新」フラグを立て、そこからそれを使用する他のすべてのタスクを更新します。

これは、アプリケーション全体のバグの明確な潜在的な原因になることに注意してください。可変性は、あらゆる種類のキャッシングを複雑にします。不変モデルに移行できれば、物事は単純化される可能性がありますが、時代遅れのオブジェクトを使用すると、それ自体が複雑になります。

于 2015-07-09T17:52:14.600 に答える