运行GC.Collect的同步GC、Collect

2023-09-02 11:58:40 作者:独活

GC.Collect的出现启动垃圾收集在一个后台线程,然后立即返回。如何运行 GC.Collect的同步 - 即等待垃圾回收完成

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?

这是在NUnit的测试范围内。我尝试添加的 gcConcurrent 设置为我的测试程序集的app.config文件,我试图同与nunit.exe.config。既没有任何影响 - 当我调试,我仍然可以看到被终结上运行的GC终结器线程,而不是所谓的 GC.Collect的线程(NUnit的的TestRunnerThread),并且两个线程同时运行

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.

背景:我想,如果他们泄露(不调用Dispose)特定类我的测试失败。所以,我添加了一个终结到类设置一个静态 wasLeaked 标志;然后我的测试TearDown中调用 GC.Collect的(),然后抛出,如果 wasLeaked 是真实的。但它不是失败的确定性,因为当它读取 wasLeaked ,终结通常甚至没有被调用呢。 (它没有一些最新测试来代替,后垃圾回收最终完成。)

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

GC.Collect();
GC.WaitForPendingFinalizers();

收集()将安排最后定稿任何非根实例,然后该线程将等待终结器线程来完成。

The Collect() will schedule any non-rooted instances for finalization and then the thread will wait for the finalizer thread to complete.