S
S
stcmd042362018-08-18 17:39:53
.NET
stcmd04236, 2018-08-18 17:39:53

How to properly release a COM object?

Good afternoon! How does Marshal.ReleaseComObject() work?
This is the object I'm using.

public class Object1C : IDisposable
    {
        private bool _disposed = false;

        public Object1C(dynamic value)
        {
            Value = value;
        }

        public dynamic Value { get; private set; }

        public Type Type => Value.GetType();

        private void ReleaseUnmanagedResources()
        {
            if (_disposed) return;
            Marshal.ReleaseComObject(Value);
            _disposed = true;
        }

        public void Dispose()
        {
            ReleaseUnmanagedResources();
            GC.SuppressFinalize(this);
        }

        ~Object1C()
        {
            ReleaseUnmanagedResources();
        }
    }

method that creates a COM connection with 1s
public void Open()
        {
            Type comconnector = Type.GetTypeFromProgID("V83.COMConnector");

            if(comconnector == null)
                throw new Exception1c($"COM Class Object \"V83.COMConnector\" was not found or not registered in the system");

            try
            {
                IV8COMConnector connectorInstance = (IV8COMConnector)Activator.CreateInstance(comconnector);
                Object1C = new Object1C(connectorInstance.Connect(ConnectionArgs.ToString())); // Здесь создается объект
            }
            catch (Exception ex)
            {
                throw new Exception1c($"{ex.Message}\r\n{ConnectionArgs}");
            }
        }

Well, in general, this is to automatically unload unmanaged resources. If you explicitly call Dispose then the program works correctly. If you don't explicitly call it, appcrash just crashes, but Dispose is called in the finalizer too.
static void Main(string[] args)
        {
            var connection = new Connection1C(new ConnectionArgs("srv", "erp", "Админ", ""));
            connection.Open();
            connection.Object1C.Dispose(); 
        }

I can't figure out what the problem is.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Alexander Yudakov, 2018-08-19
@stcmd04236

Marshal.ReleaseComObject()must be called explicitly - in the same thread (thread) where we received this COM object.
The GC is running on a different thread. You can't call there. Therefore, the destructor will have to be removed.
I use the using construct - the code remains readable.

using (var conn = new Object1C(connectorInstance.Connect(ConnectionArgs.ToString())))
{
    // Делаем необходимую работу
}

PS Don't forget to also release any 1C objects you received through this COM connection. The methodology is the same.

A
Alexander, 2018-08-18
@alexr64

Either you use the using construct , or you destroy the object yourself.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question