c# - 完成集合 Dictionary<object, IntPtr>

标签 c# .net

我有一个字段为 Dictionary<object, IntPtr> 的类.

当用户调用我类的某些方法时,我会动态分配内存:

IntPtr somePointer = Marshal.AllocHGlobal(/*some desired size*/);

然后我将在另一个线程中使用该内存。实际上,在完成一些工作后,线程通过 Marshal.FreeHGlobal 释放分配的内存。并从集合中删除适当的 key 。但是这个线程有可能崩溃,所以我正在考虑适当的终结。

我如何才能完成整个集合(以防某些线程崩溃但我的内存仍处于分配状态)?

我的倾向是改变IntPtrSafeHandle .这会有帮助吗?

最佳答案

为 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/

相关文章:

c# - 如果某些数据为空,Winforms datagridview 将不会加载数据

c# - Linq 用另一个值替换列值

c# - WinForms DataGridView 抛出 IndexOutOfRangeException

c# - 阻止进程子窗口?

c# - 有没有办法按顺序执行一个实现类

使用 Web Matrix 助手的 C# JSON 解码

c# - VS 2015 ASP.NET Web API (EF6) & Xamarin 启用迁移失败

c# - 无法使用自定义数据库初始值设定项

.net - 您可以使用 MEF 水合静态属性吗?

c# - 为什么必须添加 System.Data.Entity 才能使用 System.Data.Objects?