@@ -505,6 +505,8 @@ protected virtual void Dispose(bool disposing)
505505 {
506506 if ( ! IsDisposed )
507507 {
508+ IsDisposed = true ;
509+
508510 if ( disposing )
509511 {
510512 // We're about to dispose, notify the application.
@@ -518,15 +520,22 @@ protected virtual void Dispose(bool disposing)
518520 */
519521 lock ( resourcesLock )
520522 {
521- foreach ( GCHandle resource in resources . ToArray ( ) )
523+ /* NOTE: It is very important to make a copy of the resource handles and then clear
524+ * the array. This enables RemoveResourceReference to identify whether the handle
525+ * has already been disposed or not, to prevent us from freeing a given handle twice.
526+ * Freeing a GCHandle twice is very bad, and GCHandle.IsAllocated is not accurate once
527+ * you make a copy of the handle.
528+ */
529+ GCHandle [ ] resourceArray = resources . ToArray ( ) ;
530+ resources . Clear ( ) ;
531+ foreach ( GCHandle resource in resourceArray )
522532 {
523533 object target = resource . Target ;
524534 if ( target != null )
525535 {
526536 ( target as IDisposable ) . Dispose ( ) ;
527537 }
528538 }
529- resources . Clear ( ) ;
530539 }
531540
532541 if ( userVertexBuffer != IntPtr . Zero )
@@ -549,8 +558,6 @@ protected virtual void Dispose(bool disposing)
549558 // Dispose of the GL Device/Context
550559 FNA3D . FNA3D_DestroyDevice ( GLDevice ) ;
551560 }
552-
553- IsDisposed = true ;
554561 }
555562 }
556563
@@ -566,7 +573,9 @@ internal void AddResourceReference(GCHandle resourceReference)
566573 }
567574 }
568575
569- internal void RemoveResourceReference ( GCHandle resourceReference )
576+ /// <param name="resourceReference">The GCHandle for your resource</param>
577+ /// <returns>true if you should Free your GCHandle</returns>
578+ internal bool RemoveResourceReference ( GCHandle resourceReference )
570579 {
571580 lock ( resourcesLock )
572581 {
@@ -579,9 +588,12 @@ internal void RemoveResourceReference(GCHandle resourceReference)
579588 // Perform an unordered removal, the order of items in this list does not matter
580589 resources [ i ] = resources [ resources . Count - 1 ] ;
581590 resources . RemoveAt ( resources . Count - 1 ) ;
582- return ;
591+ return true ;
583592 }
584593 }
594+
595+ // The GCHandle was already freed, most likely by GraphicsDevice.Dispose
596+ return false ;
585597 }
586598
587599 #endregion
0 commit comments