@@ -41,7 +41,7 @@ struct PendingArgs
4141 private ConcurrentQueue < IPyDisposable > _objQueue = new ConcurrentQueue < IPyDisposable > ( ) ;
4242 private bool _pending = false ;
4343 private readonly object _collectingLock = new object ( ) ;
44- private IntPtr _pendingArgs ;
44+ private IntPtr _pendingArgs = IntPtr . Zero ;
4545
4646 #region FINALIZER_CHECK
4747
@@ -128,7 +128,7 @@ internal void AddFinalizedObject(IPyDisposable obj)
128128 _objQueue . Enqueue ( obj ) ;
129129 }
130130 GC . ReRegisterForFinalize ( obj ) ;
131- if ( _objQueue . Count >= Threshold )
131+ if ( ! _pending && _objQueue . Count >= Threshold )
132132 {
133133 AddPendingCollect ( ) ;
134134 }
@@ -164,26 +164,28 @@ internal static void Shutdown()
164164
165165 private void AddPendingCollect ( )
166166 {
167- if ( _pending )
167+ if ( Monitor . TryEnter ( _collectingLock ) )
168168 {
169- return ;
170- }
171- lock ( _collectingLock )
172- {
173- if ( _pending )
169+ try
174170 {
175- return ;
171+ if ( ! _pending )
172+ {
173+ _pending = true ;
174+ var args = new PendingArgs { cancelled = false } ;
175+ _pendingArgs = Marshal . AllocHGlobal ( Marshal . SizeOf ( typeof ( PendingArgs ) ) ) ;
176+ Marshal . StructureToPtr ( args , _pendingArgs , false ) ;
177+ IntPtr func = Marshal . GetFunctionPointerForDelegate ( _collectAction ) ;
178+ if ( Runtime . Py_AddPendingCall ( func , _pendingArgs ) != 0 )
179+ {
180+ // Full queue, append next time
181+ FreePendingArgs ( ) ;
182+ _pending = false ;
183+ }
184+ }
176185 }
177- _pending = true ;
178- var args = new PendingArgs ( ) { cancelled = false } ;
179- IntPtr p = Marshal . AllocHGlobal ( Marshal . SizeOf ( typeof ( PendingArgs ) ) ) ;
180- Marshal . StructureToPtr ( args , p , false ) ;
181- _pendingArgs = p ;
182- IntPtr func = Marshal . GetFunctionPointerForDelegate ( _collectAction ) ;
183- if ( Runtime . Py_AddPendingCall ( func , p ) != 0 )
186+ finally
184187 {
185- // Full queue, append next time
186- _pending = false ;
188+ Monitor . Exit ( _collectingLock ) ;
187189 }
188190 }
189191 }
@@ -205,8 +207,8 @@ private static int OnPendingCollect(IntPtr arg)
205207 }
206208 finally
207209 {
210+ Instance . FreePendingArgs ( ) ;
208211 Instance . ResetPending ( ) ;
209- Marshal . FreeHGlobal ( arg ) ;
210212 }
211213 return 0 ;
212214 }
@@ -244,12 +246,20 @@ private void DisposeAll()
244246 }
245247 }
246248
249+ private void FreePendingArgs ( )
250+ {
251+ if ( _pendingArgs != IntPtr . Zero )
252+ {
253+ Marshal . FreeHGlobal ( _pendingArgs ) ;
254+ _pendingArgs = IntPtr . Zero ;
255+ }
256+ }
257+
247258 private void ResetPending ( )
248259 {
249260 lock ( _collectingLock )
250261 {
251262 _pending = false ;
252- _pendingArgs = IntPtr . Zero ;
253263 }
254264 }
255265
0 commit comments