확실하게 작동 할 수있는 IntPtr입니다 래퍼를 작성. 그러나 항목이 사전에 저장되어있는 한 메모리가 유효한 상태를 유지해야하는 것은 불필요합니다. 이 경우 사용자가 직접 디렉토리에서 항목을 제거하면 자동으로 메모리를 비우는 디렉토리를 만드는 것이 클라이언트 코드에서 훨씬 쉽습니다. 클라이언트가 각 항목에 대해 Dispose()를 호출 할 필요가 없습니다. 이는 항상 장점입니다.
이렇게하려면 IDictionary<object, IntPtr>
에서 IDisposable 클래스를 파생시킵니다. 대부분의 메서드 호출을 개인 사전에 위임 할 수 있습니다. 메모리 할당을 위해 커스텀 Add(), 삭제하기 위해 Delete를 원할 것입니다. 그리고 Dispose()와 finalizer를 구현하여 정리하십시오. 코드는하지만 좀 못생긴 :
class MyDictionary : IDictionary<object, IntPtr>, IDisposable {
private Dictionary<object, IntPtr> impl = new Dictionary<object, IntPtr>();
public void Add(object key) {
IntPtr mem = Marshal.AllocCoTaskMem(666); // Something smarter here...
impl.Add(key, mem);
}
public bool Remove(object key) {
if (!impl.ContainsKey(key)) return false;
Marshal.FreeCoTaskMem(impl[key]);
return impl.Remove(key);
}
protected void Dispose(bool disposing) {
foreach (IntPtr mem in impl.Values) Marshal.FreeCoTaskMem(mem);
if (disposing) impl.Clear();
}
public void Dispose() {
Dispose(true);
}
~MyDictionary() {
Dispose(false);
}
// Boilerplate
public void Add(object key, IntPtr value) { throw new NotImplementedException(); }
public void Add(KeyValuePair<object, IntPtr> item) { throw new NotImplementedException(); }
public bool Remove(KeyValuePair<object, IntPtr> item) { throw new NotImplementedException(); }
public bool ContainsKey(object key) { return impl.ContainsKey(key); }
public ICollection<object> Keys { get { return impl.Keys; }}
public bool TryGetValue(object key, out IntPtr value) { return impl.TryGetValue(key, out value); }
public ICollection<IntPtr> Values { get {return impl.Values; }}
public IntPtr this[object key] { get { return impl[key]; } set { impl[key] = value; } }
public void Clear() { impl.Clear(); }
public bool Contains(KeyValuePair<object, IntPtr> item) { return impl.Contains(item); }
public void CopyTo(KeyValuePair<object, IntPtr>[] array, int arrayIndex) { (impl as ICollection<KeyValuePair<object, IntPtr>>).CopyTo(array, arrayIndex); }
public int Count { get { return impl.Count; }}
public bool IsReadOnly { get { return (impl as ICollection<KeyValuePair<object, IntPtr>>).IsReadOnly; } }
public IEnumerator<KeyValuePair<object, IntPtr>> GetEnumerator() { return impl.GetEnumerator(); }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return (impl as System.Collections.IEnumerable).GetEnumerator(); }
}
AllocCoTaskMem이 BTW 더 나은 할당을, 그것은 기존의 수하물이 없습니다.
가장 좋은 해결책은 관리되지 않는 메모리를 할당하지 않는 것입니다. 일부 p/Invoke 시나리오에만 해당되며 p/Invoke는 문제 설명에 언급되어 있지 않습니다.메모리를 할당하고 해제하기 때문에 실제로이 작업을 수행해야하는 것은 아닙니다. –
새 스레드가 kernel32.dll 함수에서 내 보낸 할당 된 메모리 슬롯을 그냥 통과시킵니다. 이 함수가 끝나면 그 슬롯을 할당 해제 할 것이다. –