Example requiring GC.SuppressFinalize(this)

// Do not run these tests from a Debug build or under the debugger. A standalone release build is required.usingSystem;usingSystem.Collections.Generic;usingSystem.Threading;publicclassTest:IDisposable{privatesealedclassHandleHolder{// 0 is the invalid handle valuepublicintHandle{get;set;}}privateHandleHolderhandleHolder;Test(){// Set the handle to a valid value for the testthis.handleHolder=newHandleHolder{Handle=0x1};}~Test(){Console.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+": Finalizer called");// This is just a check to ensure the constructor completedif(this.handleHolder!=null){this.CloseHandle(true);}}// This method is pretending to be a p/Invoke function to free a handlestaticDictionary<int,int>freedHandles=newDictionary<int,int>();privatestaticvoidReleaseHandle(inthandle){Console.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+": Released handle 0x"+handle.ToString("X"));if(handle==0){Console.WriteLine(" ReleaseHandle released a bad handle! Bad, bad, bad!");}else{lock(freedHandles){if(freedHandles.ContainsKey(handle)){Console.WriteLine(" ReleaseHandle double-released a handle! Bad, bad, bad!");}else{freedHandles.Add(handle,handle);}}}}privatevoidCloseHandle(boolcalledFromFinalizer){Console.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+": CloseHandle starting");// (real code)HandleHoldermyHandleHolder=this.handleHolder;if(myHandleHolder.Handle==0){// Handle is already free'dreturn;}// (code inserted to duplicate problems)if(!calledFromFinalizer){Console.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+": Garbage collection in CloseHandle!");GC.Collect();Thread.Sleep(500);// Let the finalizer thread runConsole.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+": CloseHandle continuing after garbage collection");}// (real code)ReleaseHandle(myHandleHolder.Handle);// (code inserted to duplicate problems)if(calledFromFinalizer){// With this Thread.Sleep call, you get a double handle release// Without this Thread.Sleep call, you get a bad handle releasedThread.Sleep(500);// Let the Dispose thread run [1]}// (real code)myHandleHolder.Handle=0;Console.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+": CloseHandle ending");}publicvoidDispose(){this.CloseHandle(false);// Uncomment the next line to fix the handle problems//GC.SuppressFinalize(this); [2]}staticvoidMain(){Testt=newTest();t.Dispose();Console.WriteLine("Thread "+Thread.CurrentThread.ManagedThreadId+": Returning from Main");}}