GC.Collect
appears to start the garbage collection in a background thread, and then return immediately. How can I run GC.Collect
synchronously -- i.e., wait for the garbage collection to complete?
This is in the context of NUnit tests. I tried adding the gcConcurrent setting to my test assembly's app.config file, and I tried the same with nunit.exe.config. Neither had any effect -- when I debug, I can still see the finalizer being run on the "GC Finalizer Thread", rather than the thread that called GC.Collect
(NUnit's "TestRunnerThread"), and both threads are running concurrently.
Background: I want my tests to fail if they leak (don't call Dispose on) a particular class. So I've added a finalizer to that class that sets a static wasLeaked
flag; then my test TearDown calls GC.Collect()
and then throws if wasLeaked
is true. But it's not failing deterministically, because when it reads wasLeaked
, the finalizer usually hasn't even been called yet. (It fails some later test instead, after the garbage collection finally finishes.)
Finalizers are run on a dedicated, high-priority background thread. From the background in your post, I gather that you can simply do
The
Collect()
will schedule any non-rooted instances for finalization and then the thread will wait for the finalizer thread to complete.A easier/better way of doing this may be to use mocking and check an expectation that Dispose was called explicitly.
Example using RhinoMocks
If the method needs to create and then dispose of the object, then I would use and inject a factory class that is able to create the mock object. Example below uses stub on factory as it's not what we are testing for in this test.
Finalizers always run on a separate thread regardless of whether you're using a concurrent GC or not. If you want to ensure that finalizers have been run, try
GC.WaitForPendingFinalizers
instead.You can use
GC.RegisterForFullGCNotification
, trigger a full collection withGC.Collect(GC.MaxGeneration)
and then theGC.WaitForFullGCComplete
andGC.WaitForPendingFinalizers
methods, but make sure to use this in your tests only, they should not be used for production code.