C # COM объект не покидает память

1

У меня есть 10 потоков, каждый поток создает новый экземпляр моего объекта. Вызовите 2 метода этого объекта и циклический ресурс конца потока, проблема в том, что он остается в памяти.

С этим одним часом в конечном итоге происходит одна из памяти.

У меня есть следующий код:

        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);
        new Thread(Thread_).Start();
        Thread.Sleep(1000);

void Thread_()
{
    spdNFeX _spdNFeX = new spdNFeX();
    try
    {
        String[] Chave = (String[])Chaves.ToArray(typeof(string));

        _spdNFeX.LoadConfig("");
        Random Rand = new Random();
        _spdNFeX.DiretorioLog = "C:\\Users\\Joao\\Documents\\Visual Studio 2012\\Projects\\TesteNFe\\TesteNFe\\bin\\Debug\\" + Convert.ToString(Rand.Next(1, 999) + "\\");

        for (int i = 0; i < Chave.Length; i++)
        {
            _spdNFeX.ConsultarNF(Chave[i]);
            Thread.Sleep(5000);
        }
    }
    finally {
        _spdNFeX = null;
    }

}

Я выполнил следующие тесты, но безуспешно.

Тест 1

finally {
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(_spdNFeX);
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

Тест 2

finally {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(_spdNFeX);
        _spdNFeX = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

Тест 3

public class ComDisposer : IDisposable
{
    private List<Object> _comObjs;

    public ComDisposer()
    {
        _comObjs = new List<Object>();
    }

    ~ComDisposer()
    {
        Dispose(false);
    }

    public T Add<T>(T o)
    {
        if (o != null && o.GetType().IsCOMObject)
            _comObjs.Add(o);
        return o;
    }

    public void Clear()
    {
        Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            for (int i = _comObjs.Count - 1; i >= 0; --i)
                Marshal.FinalReleaseComObject(_comObjs[i]);
            _comObjs.Clear();
        }
    }

    void IDisposable.Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}        

void Thread_()
{
    using (ComDisposer cd = new ComDisposer())
    {
        spdNFeX _spdNFeX = cd.Add(new spdNFeX());
        try
        {
            String[] Chave = (String[])Chaves.ToArray(typeof(string));

            _spdNFeX.LoadConfig("");
            Random Rand = cd.Add(new Random());
            _spdNFeX.DiretorioLog = "C:\\Users\\Joao\\Documents\\Visual Studio 2012\\Projects\\TesteNFe\\TesteNFe\\bin\\Debug\\" + Convert.ToString(Rand.Next(1, 999) + "\\");

            for (int i = 0; i < Chave.Length; i++)
            {
                _spdNFeX.ConsultarNF(Chave[i]);
                Thread.Sleep(5000);
            }
        }
        finally
        {

        }
    }
}
  • 2
    Какой бы ни был spdNFeX, я бы попытался вызвать Dispose прежде чем обнулять его, если это COM-объект.
  • 0
    Как я мог это сделать? Ранее пытался использовать этот интерфейс IDisposable, но безуспешно.
Показать ещё 5 комментариев
Теги:
thread-safety

1 ответ

0
Лучший ответ

Используйте System.Runtime.InteropServices.Marshal.FinalReleaseComObject.

  • 1
    Это редко является правильным ответом и часто вносит больше ошибок.
  • 0
    @ScottChamberlain Если вы не используете объект после релиза, он работает просто отлично. Это просто заставляет счетчик ссылок на 0.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню