ObjectDisposedException was unhandled: Safe handle has been closed at program end

14,190

Solution 1

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

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.

Solution 2

Are any of your types Disposable? Try disposing all of your disposable resources before exiting the application.

Share:
14,190
Mike Wills
Author by

Mike Wills

After going to school to become a network administrator, Mike, fell in love with programming. He has been a midrange (IBM i, iSeries, AS/400) developer since 2000. He has since added ASP.NET to to his toolbox (around 2006) and now does dual duty writing/supporting green-screen applications and ASP.NET internet and intranet applications. He does a lot of integration between the IBM i and ASP.NET. Besides his programming day job, he dabbles in PHP and many other areas of tech. You can find him on his website, @MikeWills, Facebook, and Google+

Updated on July 29, 2022

Comments

  • Mike Wills
    Mike Wills almost 2 years

    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.