@stcmd04236

Как правильно освободить COM объект?

Добрый день! Как работает Marshal.ReleaseComObject()?

Это объект которую использую.
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();
        }
    }


метод который создает COM соединение с 1с

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}");
            }
        }


Ну в общем это для того чтобы автоматически выгрузить неуправлямые ресурсы. Если явно вызвать Dispose тогда програмка работает корректно. Если явно не вызвать просто вылетает appcrashом но при этом Dispose вызывается и в финализаторе тоже.

static void Main(string[] args)
        {
            var connection = new Connection1C(new ConnectionArgs("srv", "erp", "Админ", ""));
            connection.Open();
            connection.Object1C.Dispose(); 
        }


Не могу понят в чем проблема.
  • Вопрос задан
  • 1376 просмотров
Решения вопроса 1
AlexanderYudakov
@AlexanderYudakov
C#, 1С, Android, TypeScript
Marshal.ReleaseComObject() нужно вызывать явно — в том же самом потоке (thread), где мы получили этот COM-объект.
GC работает в другом потоке. Там вызывать нельзя. Поэтому деструктор придется убрать.

Я использую конструкцию using — код остается читабельным.

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


P.S. Не забывайте также освобождать любые 1С-объекты, полученные вами через это COM-соединение. Методика та же.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Или вы используете конструкцию using, или уничтожаете объект сами.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы