Completion of collection Dictionary <object, IntPtr>

I have a class with a field Dictionary<object, IntPtr>.

I allocate memory dynamically when the user calls some method of my class:

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

Then I will use this memory in another thread. In fact, after doing some work, the thread frees the allocated memory through Marshal.FreeHGlobaland removes the corresponding key from the collection. But there is a chance that this thread will crash, so I am thinking about the correct finalization.

How can I complete this assembly (in case some thread crashes and my memory still remains allocated)?

My tilt is changing IntPtrto SafeHandle. Will this help?

+3
3

IntPtr, , . , , . , , , . , Dispose() , .

IDictionary<object, IntPtr> IDisposable. . , Add() , Delete, . 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 - btw, .

+1

, try/finally , , , , ( , , ?), finally .

SafeHandle , Dispose, , , SafeHandle . , .

, WeakReference, , , SafeHandle try/finally.

+1

I think you will find that SafeHandle just calls CloseHandle on cleanup, which I don’t think is the same as FreeHGlobal.

You should probably add the full Dispose / Finalizer template to your class that contains the collection and pass it through the dictionary and clear it.

Or write a wrapper with a finalizer for HGlobal.

Update: this may be useful - http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/f74b7c3c-12c4-466b-9754-82e9dea8b83e

+1
source

Source: https://habr.com/ru/post/1755137/


All Articles