2009-11-06 5 views
11

저는 쓰는 작은 취미 게임을위한 간단한 리소스 관리자를 작성하려고합니다. 이 자원 관리자가 수행해야하는 작업 중 하나는 사용하지 않는 자원을 언로드하는 것입니다. 나는 두 가지 방법으로이 일을 생각할 수 있습니다 :C# - 개체에 대한 참조 수를 얻으십시오.

  • 객체가 더 이상, 그것은 더 이상 그것을 사용하는 의미하지하기 위해 리소스 관리자 하는 방법을 호출해야합니다 자원에 참조를 필요로하는 경우; 또는

  • 객체가 더 이상 자원에 참조를 필요로

    , 그것은 단순히 는 null로 설정합니다. 그런 다음 리소스 관리자가 사용하지 않는 리소스 인 을 언로드하라는 메시지를 받으면 개의 리소스가 각각 (리플렉션을 통해) 참조 카운트가됩니다. 참조 카운트가 인 경우 (리소스 관리자는 에 리소스에 대한 참조가 있음) 리소스를 언로드합니다.

C#의 두 번째 솔루션을 구현할 방법이 있습니까? 감사합니다. .

+0

리소스 관리자는 Garbace Collector에서 수행하지 않는 작업은 무엇입니까? – CannibalSmith

+1

@CannibalSmith - 일반적으로 여러 비트의 코드가 리소스 (본질적으로 캐시)를 다시 사용할 수 있도록 허용 –

+0

한 번에 하나의 이미지 만로드되도록 이미지로드 하나의 버전은 메모리에있을 수 있음). –

답변

11

리소스 관리자의 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) 
} 
+0

나는 이것을 할 것이다 :) 한 가지 : 나는 틀릴 수도 있지만, 사전에서 올바른 참조를 얻어서 반환하기 전에 null인지 확인해야한다고 생각한다. "(wr.IsAlive)가 wr.Target을 반환하는 경우"수행하면 강력한 참조를 취하지 않으므로 IsAlive가 true를 반환 할 수 있지만 값을 반환 할 때 wr.Target이 수집되었을 수 있습니다. 여기에 대체 코드 샘플이 있습니다. http://msdn.microsoft.com/en-us/library/system.weakreference.aspx –

+1

'object'는 수집을 방지 할만큼 강력합니다. 그것은 "null"이거나 강할 것이다. 호출자는 그것을 * 형 * 참조로 만들기 위해 캐스팅해야하지만 다른 문제입니다. –

+0

.NET 4.5에는 WeakReference의 일반 버전이 있습니다. http://www.philosophicalgeek.com/2014/08/14/prefer- weakreferencecetreference-> weakreference / – Logerfo

2

이미 가비지 수집기라고하는 .NET의 리소스 관리자가 있습니다. 따라서 매우 효율적인 접근법은 참조를 null로 설정하고 아무 것도 수행하지 않는 것입니다.

더 많은 직접적인 대답 : 아니오, 참조를 에서으로 가져 오는 방법은 없습니다.

WeakReference class을 학습하거나 캐싱 시스템을 사용할 수 있습니다.

1

자원 관리자가 자원에 WeakReference을 사용하는지 확인하십시오. 그렇게하면 아무도 자원을 참조하지 않을 때 가비지 콜렉션을받을 수 있습니다.

0

으로 이미 이미 GC에 의해 이루어집니다 달성하기 위해 노력하고 있으며, 벌금 WeakReference를 사용하여 튜닝 할 수있는 다른 사용자에 의해 말했다.

이는 .NET, java 등의 관리 환경에서는 문제가되지 않는다는 것을 의미합니다.

낮은 수준의 프레임 워크 아키텍처는 메모리 관리에서 당신을 격리하므로, 그런 종류의 기능이 여전히 필요한 경우에는 자신의 코드 아키텍처를 검토하여 사용자가 기억 관리의 나쁜 실습

28

몇 가지. 우선, 객체는 참조 카운팅되지 않습니다. 참조 계산 방식은 순환 참조 문제가있어서 두 객체가 서로를 참조하지만 접근 할 수 없으므로 누출됩니다. .NET은 참조 횟수를 사용하지 않는 마크 앤 스위프 방식을 사용합니다.

둘째, 약한 참조를 사용하라는 제안은 끔찍한 것이 아니지만 슬램 덩크가 아닙니다. 성능상의 이유로 캐시를 구축하고 있습니다.(응용 프로그램의 성능 특성에 대한 신중하고 경험적이며 현실적인 연구를 통해 허용 가능한 성능을 달성하기 위해 캐싱 전략이 필요하다는 것을 설득력있게 입증했다고 가정합니다. 그렇지 않은 경우 이러한 결정을 성급하게 내리고 있습니다.) 캐시는 리소스를 해제 할 때 정책을 가져야합니다. 그렇지 않으면 메모리 누수가 발생합니다.

GC 정책과 정책이 동일한 정책이라는 것을 어떻게 알 수 있습니까? GC는 사용자의 특정 성능을 염두에두고 설계되지 않았습니다. 즉, 실제로 쓰레기가 아닌 특정 성능 목표를 달성하기 위해 자원을 출시하도록 설계되었습니다. 결정을 GC에 위임하면 성능 요구에 맞게 캐시 정책을 조정할 수있는 능력을 포기하게됩니다.

관련 문제