@@ -111,7 +111,7 @@ public void AttachDevice(ID3D11Device1 device)
111111 {
112112 ThrowIfDisposed ( ) ;
113113 StopCaptureCore ( ) ;
114- DisposeWinRt ( _winRtDevice ) ;
114+ WinRtThreading . Release ( _winRtDevice ) ;
115115 _winRtDevice = winRtDevice ;
116116 StartCaptureCore ( ) ;
117117 }
@@ -123,7 +123,7 @@ public void DetachDevice()
123123 lock ( _gate )
124124 {
125125 StopCaptureCore ( ) ;
126- DisposeWinRt ( _winRtDevice ) ;
126+ WinRtThreading . Release ( _winRtDevice ) ;
127127 _winRtDevice = null ;
128128 }
129129 }
@@ -229,12 +229,8 @@ public bool TryPresent(ID3D11DeviceContext1 context, ID3D11Texture2D destination
229229 }
230230 finally
231231 {
232- // Close the surface RCW on this thread. Leaving it for the GC
233- // finalizer AVs in Store-packaged processes: those WinRT objects
234- // are apartment-bound and Marshal.Release from GC.RunFinalizers
235- // is the 0xC0000005 that closes the app a few seconds after resize.
236- DisposeWinRt ( surface ) ;
237- DisposeWinRt ( frame ) ;
232+ WinRtThreading . Release ( surface ) ;
233+ WinRtThreading . Release ( frame ) ;
238234 }
239235 }
240236
@@ -256,7 +252,7 @@ public void Dispose()
256252 _disposed = true ;
257253 StopCaptureCore ( ) ;
258254 ReleaseCaptureItem ( ) ;
259- DisposeWinRt ( _winRtDevice ) ;
255+ WinRtThreading . Release ( _winRtDevice ) ;
260256 _winRtDevice = null ;
261257 }
262258 }
@@ -268,8 +264,12 @@ private void StartCaptureCore()
268264 return ;
269265 }
270266
267+ WinRtThreading . EnsureDispatcherQueue ( ) ;
271268 _contentSize = SanitizeSize ( _captureItem . Size ) ;
272- Direct3D11CaptureFramePool framePool = Direct3D11CaptureFramePool . CreateFreeThreaded (
269+ // Create, not CreateFreeThreaded: frames and their RCWs must be born
270+ // on this dispatcher. Free-threaded FrameArrived ran on a worker,
271+ // and those IObjectReferences finalized with 0xC0000005 in the Store.
272+ Direct3D11CaptureFramePool framePool = Direct3D11CaptureFramePool . Create (
273273 _winRtDevice ,
274274 DirectXPixelFormat . B8G8R8A8UIntNormalized ,
275275 2 ,
@@ -307,13 +307,19 @@ private void StopCaptureCore()
307307 framePool . FrameArrived -= FramePool_FrameArrived ;
308308 }
309309
310- DisposeWinRt ( captureSession ) ;
311- DisposeWinRt ( framePool ) ;
312- DisposeWinRt ( pendingFrame ) ;
310+ WinRtThreading . Release ( captureSession ) ;
311+ WinRtThreading . Release ( framePool ) ;
312+ WinRtThreading . Release ( pendingFrame ) ;
313313 }
314314
315315 private void FramePool_FrameArrived ( Direct3D11CaptureFramePool sender , object args )
316316 {
317+ if ( ! _dispatcher . CheckAccess ( ) )
318+ {
319+ _ = _dispatcher . BeginInvoke ( ( ) => FramePool_FrameArrived ( sender , args ) ) ;
320+ return ;
321+ }
322+
317323 Direct3D11CaptureFrame ? frame = null ;
318324 try
319325 {
@@ -328,7 +334,7 @@ private void FramePool_FrameArrived(Direct3D11CaptureFramePool sender, object ar
328334 {
329335 if ( ! ReferenceEquals ( sender , _framePool ) || _isFrozen )
330336 {
331- DisposeWinRt ( frame ) ;
337+ WinRtThreading . Release ( frame ) ;
332338 return ;
333339 }
334340
@@ -337,15 +343,15 @@ private void FramePool_FrameArrived(Direct3D11CaptureFramePool sender, object ar
337343 // Recreate discards native frames. Close the pending wrapper
338344 // first so its finalizer cannot Release a pointer Recreate
339345 // has already invalidated.
340- DisposeWinRt ( _pendingFrame ) ;
346+ WinRtThreading . Release ( _pendingFrame ) ;
341347 _pendingFrame = null ;
342348 _contentSize = size ;
343349 sender . Recreate (
344350 _winRtDevice ! ,
345351 DirectXPixelFormat . B8G8R8A8UIntNormalized ,
346352 2 ,
347353 size ) ;
348- DisposeWinRt ( frame ) ;
354+ WinRtThreading . Release ( frame ) ;
349355 frame = null ;
350356 }
351357 }
@@ -361,7 +367,7 @@ private void FramePool_FrameArrived(Direct3D11CaptureFramePool sender, object ar
361367 long previous = Interlocked . Read ( ref _lastAcceptedTimestamp ) ;
362368 if ( previous != 0 && now - previous < minimumTicks )
363369 {
364- DisposeWinRt ( frame ) ;
370+ WinRtThreading . Release ( frame ) ;
365371 return ;
366372 }
367373
@@ -370,23 +376,30 @@ private void FramePool_FrameArrived(Direct3D11CaptureFramePool sender, object ar
370376 {
371377 if ( ! ReferenceEquals ( sender , _framePool ) || _isFrozen )
372378 {
373- DisposeWinRt ( frame ) ;
379+ WinRtThreading . Release ( frame ) ;
374380 return ;
375381 }
376382
377383 Direct3D11CaptureFrame ? replaced = _pendingFrame ;
378384 _pendingFrame = frame ;
379385 frame = null ;
380- DisposeWinRt ( replaced ) ;
386+ WinRtThreading . Release ( replaced ) ;
381387 }
382388
383389 FrameAvailable ? . Invoke ( ) ;
384390 }
385391 catch ( Exception exception )
386392 {
387- DisposeWinRt ( frame ) ;
393+ WinRtThreading . Release ( frame ) ;
388394 CaptureFailed ? . Invoke ( exception ) ;
389395 }
396+ finally
397+ {
398+ if ( args is IWinRTObject && ! ReferenceEquals ( args , sender ) )
399+ {
400+ WinRtThreading . Release ( args ) ;
401+ }
402+ }
390403 }
391404
392405 private void CaptureItem_Closed ( GraphicsCaptureItem sender , object args )
@@ -438,9 +451,7 @@ private void ReleaseCaptureItem()
438451 }
439452
440453 _captureItem . Closed -= CaptureItem_Closed ;
441- // GraphicsCaptureItem is not IClosable. Drop the RCW's COM pointer here
442- // so IObjectReference.Finalize never Release's it from the GC thread.
443- DisposeWinRt ( _captureItem ) ;
454+ WinRtThreading . Release ( _captureItem ) ;
444455 _captureItem = null ;
445456 }
446457
@@ -480,32 +491,6 @@ private static WinRtDirect3DDevice CreateWinRtDevice(IDXGIDevice dxgiDevice)
480491
481492 private void VerifyDispatcherAccess ( ) => _dispatcher . VerifyAccess ( ) ;
482493
483- private static void DisposeWinRt ( object ? value )
484- {
485- if ( value is null )
486- {
487- return ;
488- }
489-
490- try
491- {
492- if ( value is IDisposable disposable )
493- {
494- disposable . Dispose ( ) ;
495- return ;
496- }
497-
498- if ( value is IWinRTObject winrt )
499- {
500- winrt . NativeObject . Dispose ( ) ;
501- }
502- }
503- catch ( Exception exception )
504- {
505- Debug . WriteLine ( $ "[LiveView] WinRT release failed: { exception } ") ;
506- }
507- }
508-
509494 [ DllImport ( "d3d11.dll" , ExactSpelling = true ) ]
510495 private static extern int CreateDirect3D11DeviceFromDXGIDevice (
511496 nint dxgiDevice ,
0 commit comments