I have a .NET 4 C# console application. It pulls data from our IBM i and sends it to our internet SQL Server. It works perfect until it ends, I get the following error:
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:
My program code is:
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());
}
}
In the console, I see the begin time and the end time. So I know the final line does get executed. What am I forgetting or not doing that I should be?
Update: The Sync* methods pull data from the IBM into an object then uses entity framework to insert the records into the database.
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;
}
All of the methods operate similar to this one.
A little bit of Googling reveals some scattered reports of the same error when using the iDB2Connection family of database access methods. Evidently IBM is relying on .Net 1.1 handling of EventHandles which changed in the move to .Net 2.0 per this Connect article.
It seems the only reprieve is to update to the latest version of the IBM drivers (using the S21917 service pack for 5.3 or SI37892 for 5.4 as you note).
Are you calling Close()
on the SafeWaitHandle
for a WaitHandle
?
WaitHandle wh = ...;
wh.SafeWaitHandle.Close(); // will throw ObjectDisposedException
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.