2011-10-27 59 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

相关问题