2014-09-03 79 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