c# - GC.WaitForPendingFinalizers 在异步方法中不起作用?

标签 c# wpf garbage-collection async-await

我有一些单元测试来验证使用弱引用的对象是否正常工作。将这些对象重构为异步工作后,单元测试失败。这似乎是由于使用异步时 GC.WaitForPendingFinalizers 不工作(或工作方式不同?)引起的。

为了检查这一点,我创建了一个带有两个按钮的简单 WPF 应用程序,一个具有常规单击事件,一个具有异步单击事件。

当我按下 NormalGCTest 按钮时,会显示“对象垃圾收集:True”。

但是当我按下 AsyncGCTest 按钮时,会显示“对象垃圾收集:False”。

这是怎么回事?有没有办法在我的测试中强制进行完整的垃圾收集?

    private void NormalGCTest(object sender, RoutedEventArgs e)
    {
        var temp1 = new object();
        var temp2 = new WeakReference(temp1);
        temp1 = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        temp1 = temp2.Target;
        System.Diagnostics.Debug.WriteLine("object garbage collected: {0}", temp1 == null);
    }

    private async void AsyncGCTest(object sender, RoutedEventArgs e)
    {
        var temp1 = new object();
        var temp2 = new WeakReference(temp1);
        temp1 = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        temp1 = temp2.Target;
        System.Diagnostics.Debug.WriteLine("object garbage collected: {0}", temp1 == null);
        await Task.Delay(0);
    }

最佳答案

对我来说,它已经工作得很好 - 我得到 True/True 。但是,您可以尝试一些事情来澄清正在发生的事情 - 例如:

var wr = CreateWeakReference();
Console.WriteLine("object available: {0}", wr.Target != null);
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
Console.WriteLine("object garbage collected: {0}", wr.Target == null);

static WeakReference CreateWeakReference()
{
    return new WeakReference(new object());
}

这使用较少的本地变量,这可能会导致困惑,具体取决于编译器如何翻译 C#。它还使用了更激进的GC.Collect .

但重要的是:停止调用垃圾收集器。你几乎不应该这样做。最后的想法 - 你可能想避免async void 。是的,我知道这是一个事件处理程序,但是一个很好的技巧是立即调用非 async void方法(如有必要,使用await)。

关于c# - GC.WaitForPendingFinalizers 在异步方法中不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21938673/

相关文章:

c# - 为什么 EF Core 2.2.6 不进行垃圾收集?

performance - Scala:可变对象与不可变对象(immutable对象)性能 - OutOfMemoryError

java - 垃圾收集器无法释放 JBoss 7.1.1 上的内存,导致 Full GC

c# - ObservableCollection 教程?

wpf - 如何让箭头指向我的边框?

c# - JQuery 选项卡控件 : load gridview

c# - 为什么一个asp :DropDownList and a asp:TextBox of the same width appear differently

c# - 从 .NET 2.0 应用程序调用 .NET 4.0 WPF 类库

c# - 从 blob 存储中获取资源文件并添加到 azure 批处理中的任务

c# - 如何将数组转换为 sql 的引号和逗号分隔字符串?