2011-10-27 104 views
3

我有一個.NET 4 C#控制檯應用程序。它從IBM i中提取數據並將其發送到我們的Internet SQL Server。它完美的作品,直到它結束,我得到以下錯誤:ObjectDisposedException未處理:程序結束時已關閉安全句柄

System.ObjectDisposedException was unhandled Message=Safe handle has been closed Source=mscorlib ObjectName="" StackTrace: at System.Runtime.InteropServices.SafeHandle.DangerousRelease() at System.Threading.RegisteredWaitHandleSafe.Finalize() InnerException:

我的程序代碼是:

class Program 
{ 
    static void Main(string[] args) 
    { 
     System.Console.WriteLine("Begin: " + DateTime.Now.ToString()); 
     SystemCodeController sc = new SystemCodeController(); 
     sc.SyncSystemCodes(); 
     ParkingTicketController pt = new ParkingTicketController(); 
     pt.SyncParkingTickets(); 
     EmailHelper.SendSuccessEmail(); 
     System.Console.WriteLine("End: " + DateTime.Now.ToString()); 
    } 
} 

在控制檯中,我看到了開始時間和結束時間。所以我知道最後一行確實會被執行。我該怎麼忘記或不這樣做?

更新:Sync *方法將數據從IBM中抽取到對象中,然後使用實體框架將記錄插入到數據庫中。

public void SyncParkingTickets() 
{ 
    ptr.ClearTable(); 
    ptr.InsertNewCitation(ibmI.GetAllCitations()); 
    ptr.SaveChanges(); 
} 

public void InsertNewCitation(IEnumerable<ParkingTicket> citations) 
{ 
    foreach (ParkingTicket citation in citations) 
    { 
     InsertNewCitation(citation); 
    } 
} 

public void InsertNewCitation(ParkingTicket citation) 
{ 
    db.AddToParkingTickets(citation); 
} 

public IEnumerable<ParkingTicket> GetAllCitations() 
{ 
    SystemCodeRepository scr = new SystemCodeRepository(); 

    // Create SQL statement 

    DataTable dt = new DataTable(); 
    using (iDB2Connection conn = new iDB2Connection(_connString)) 
    { 
     using (iDB2Command cmd = new iDB2Command(sb.ToString(), conn)) 
     { 
      conn.Open(); 
      using (iDB2DataAdapter da = new iDB2DataAdapter(cmd)) { da.Fill(dt); } 
      conn.Close(); 
     } 
    } 

    #region Fill object from DataTable 
    var citations = from i in dt.AsEnumerable() 
        select new ParkingTicket 
        { 
         // Fill object 
        }; 
    #endregion 

    return citations; 
} 

所有的方法都與此類似。

+0

什麼的'同步*'家庭電話的呢?我們可以看到這些代碼嗎?我敢打賭它漏了一個WaitHandle。 – user7116

+0

我不知道'WaitHandle'是什麼,所以我可能只是間接使用它。 –

+0

我已經將它跟蹤到IBM的驅動程序,我已經更新了我的答案以反映此問題以及可能的解決方法。 – user7116

回答

7

使用iDB2Connection系列數據庫訪問方法時出現同樣錯誤的一點點Googling reveals some scattered reports。顯然,IBM正在依靠.Net 1.1處理EventHandles,並將其轉移到.Net 2.0 per this Connect article

似乎唯一的緩存是更新到最新版本的IBM驅動程序(使用S21917 Service Pack for 5.3或SI37892 for 5.4)。


你叫上SafeWaitHandleWaitHandleClose()

WaitHandle wh = ...; 

wh.SafeWaitHandle.Close(); // will throw ObjectDisposedException 

From MSDN

When you assign a new value to the SafeWaitHandle property, the previous handle will be closed when the previous SafeWaitHandle object is collected. Do not manually close the handle, because this results in an ObjectDisposedException when the SafeWaitHandle attempts to close the handle.

+2

Woah,這是一個糟糕的實施。調用導致ObjectDisposedException的Dispose方法? – ordag

+0

@ordag:實際上ObjectDisposedException是從代碼中拋出,通常在另一個線程中,依賴於處置的事件句柄! – user7116

+0

好的...我使用5.4而不是5.3來訪問客戶端。無論如何,我正在下載最新的補丁。我有一種感覺,這會讓我們更快地到達最新版本的iSeries Access。哪個是PITA。所有項目必須一次升級,因爲您無法一次安裝多個版本的驅動程序。 –

2

是否有任何類型Disposable?在退出應用程序之前嘗試處理所有可支配資源。

+0

這是我發佈後的第一個想法。我確信我的代碼都沒有'IDisposable'。這沒有幫助。我現在確保我觸摸的每個對象都包含'.Dispose()'。 –

+0

@MikeWills:添加'IDisposable'並不奇怪地解決了'SafeHandle'使用問題。您需要查看代碼以瞭解SafeHandle或其派生類的用法。可能有一些與WaitHandle相關的代碼有問題。 – user7116

+1

就像我上面說的,我不知道'WaitHandle'是什麼,所以我可能只是間接使用它。 –

0

我有一個平等的情況。存在的問題是SafeHandle.ReleaseHandle中的P/Invoke呼叫會產生一些魔法,並呼叫System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success),該呼叫在處置後會嘗試對SafeHandle執行某些操作。

它不是你自己的SafeHandle執行不是嗎?否則,你可以嘗試擴展CriticalHandle

+0

不,我沒有做過那樣的事情。這是一個已知的錯誤?有沒有解決辦法?我希望在實施這項活動時遇到問題。 –

+0

我有同樣的錯誤(當然不同的應用程序)。但看過之後,我認爲我錯了。看到我上面的編輯。 – ordag

相關問題