2014-09-03 81 views
1

我有10个线程,每个线程都创建了我的对象的一个​​新实例。调用这个对象的2个方法和线程的循环寿命结束,问题是它保留在内存中。C#COM对象不会离开内存

随着那一小时最终发生一个内存不足。

我有以下代码:

 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对象。 – BradleyDotNET 2014-09-03 18:33:03

+0

我怎么能这样做?以前曾尝试使用这个IDisposable接口,但没有成功。 – 2014-09-03 18:39:54

+1

你不能,COM对象不是一次性的。忽略该评论。使用内存分析器收集事实。并考虑死锁的终结器线程的可能性。 – 2014-09-03 18:40:42

回答

0

使用System.Runtime.InteropServices.Marshal.FinalReleaseComObject

+1

这很少是正确的答案,通常会引入更多的错误。 – 2014-09-03 18:50:42

+0

@ScottChamberlain假设你在发布后不使用这个对象,它就可以正常工作。它只是强制引用计数为0。 – Zer0 2014-09-03 19:00:36