我有一个字段为 Dictionary<object, IntPtr>
的类.
当用户调用我类的某些方法时,我会动态分配内存:
IntPtr somePointer = Marshal.AllocHGlobal(/*some desired size*/);
然后我将在另一个线程中使用该内存。实际上,在完成一些工作后,线程通过 Marshal.FreeHGlobal
释放分配的内存。并从集合中删除适当的 key 。但是这个线程有可能崩溃,所以我正在考虑适当的终结。
我如何才能完成整个集合(以防某些线程崩溃但我的内存仍处于分配状态)?
我的倾向是改变IntPtr
至 SafeHandle
.这会有帮助吗?
最佳答案
为 IntPtr 编写一个包装器当然可以。但如果只要项目存储在字典中,内存就应该保持有效,则没有必要。如果是这种情况,如果您创建自己的目录,客户端代码会容易得多,当从字典中删除项目时,该目录会自动释放内存。客户端无需为每个项目调用 Dispose(),这始终是一个优势。
为此,从 IDictionary<object, IntPtr>
派生您自己的类和 IDisposable。您可以简单地将大部分方法调用委托(delegate)给私有(private)字典。您需要一个自定义的 Add() 来分配内存,删除以释放它。并实现 Dispose() 和终结器进行清理。虽然代码有点难看:
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 是更好的分配器,顺便说一句,它没有遗留的包袱。
关于c# - 完成集合 Dictionary<object, IntPtr>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3272919/